@@ -31,15 +31,63 @@ THE SOFTWARE.
3131#include " axmol/base/Utils.h"
3232#include " axmol/scene/Node.h"
3333#include " axmol/renderer/Renderer.h"
34+ #include " axmol/renderer/RenderTexturePass.h"
3435#include " axmol/renderer/Texture2D.h"
3536#include " axmol/renderer/Shaders.h"
3637#include " axmol/rhi/ProgramState.h"
3738#include " axmol/rhi/RenderTarget.h"
3839#include " axmol/rhi/DriverContext.h"
3940#include " axmol/scene/Camera.h"
41+ #include " axmol/math/Vec4.h"
42+
43+ #include < cmath>
4044
4145namespace ax
4246{
47+
48+ static constexpr float GRID_BLIT_ORDER = RT_PASS_END_ORDER - 1 ;
49+
50+ static bool projectGridPointToCanvas (const Mat4& projection, const Vec3& point, const Vec2& size, Vec2& out)
51+ {
52+ if (size.width <= 0 .0f || size.height <= 0 .0f )
53+ return false ;
54+
55+ Vec4 clip (point.x , point.y , point.z , 1 .0f );
56+ projection.transformVector (&clip);
57+
58+ if (std::abs (clip.w ) <= 0 .000001f )
59+ return false ;
60+
61+ const float ndcX = clip.x / clip.w ;
62+ const float ndcY = clip.y / clip.w ;
63+ out.set ((ndcX + 1 .0f ) * 0 .5f * size.width , (ndcY + 1 .0f ) * 0 .5f * size.height );
64+ return true ;
65+ }
66+
67+ static Vec2 projectGridTexCoordToCanvas (const Mat4& projection,
68+ const Vec3& point,
69+ const Vec2& size,
70+ bool flipped,
71+ const Vec2& fallbackUV)
72+ {
73+ Vec2 projected;
74+ if (!projectGridPointToCanvas (projection, point, size, projected))
75+ return fallbackUV;
76+
77+ Vec2 uv (projected.x / size.width , projected.y / size.height );
78+ if (flipped)
79+ uv.y = 1 .0f - uv.y ;
80+ return uv;
81+ }
82+
83+ static Vec3 projectGridVertexToCanvas (const Mat4& projection, const Vec3& point, const Vec2& size)
84+ {
85+ Vec2 projected;
86+ if (projectGridPointToCanvas (projection, point, size, projected))
87+ return Vec3 (projected.x , projected.y , 0 .0f );
88+
89+ return point;
90+ }
4391// implementation of GridBase
4492
4593bool GridBase::initWithSize (const Vec2& gridSize)
@@ -157,40 +205,29 @@ void GridBase::setGridRect(const ax::Rect& rect)
157205
158206void GridBase::beforeDraw ()
159207{
160- Director* director = Director::getInstance ();
161-
162- auto * renderer = director->getRenderer ();
163- auto * groupCommand = renderer->getNextGroupCommand ();
164- groupCommand->init (0 );
165- renderer->addCommand (groupCommand);
166- renderer->pushGroup (groupCommand->getRenderQueueID ());
208+ AX_SAFE_RELEASE (_renderTarget);
209+ _renderTarget = axdrv->createRenderTarget (_texture->getRHITexture ());
167210
168- auto beforeDrawCommandFunc = [director, renderer, this ]() -> void {
169- Vec2 size = director->getCanvasSizeInPixels ();
170- renderer->setViewport (0 , 0 , (unsigned int )size.width , (unsigned int )size.height );
211+ if (!_renderTexturePass)
212+ {
213+ _renderTexturePass = RefPtr<RenderTexturePass>(RenderTexturePass::obtain (), tlx::adopt_object);
214+ _renderTexturePass->setCameraOverrideEnabled (false );
215+ }
171216
172- _oldRenderTarget = renderer->getRenderTarget ();
173- AX_SAFE_RELEASE (_renderTarget);
174- _renderTarget = axdrv->createRenderTarget (_texture->getRHITexture ());
175- renderer->setRenderTarget (_renderTarget);
176- };
177- renderer->addCallbackCommand (beforeDrawCommandFunc);
217+ _renderTexturePass->setTarget (_renderTarget);
218+ _renderTexturePass->setViewport (
219+ Viewport (0 , 0 , static_cast <int >(_texture->getWidth ()), static_cast <int >(_texture->getHeight ())));
220+ _renderTexturePass->begin ();
178221
179- // since we use clearCommand, should call at here to avoid iterator damage
180- renderer->clear (TargetBufferFlags::COLOR , _clearColor, 1 , 0 , 0.0 );
222+ _renderTexturePass->clear (ClearFlag::COLOR , {.color = _clearColor, .depth = 1 .0f , .stencil = 0 });
181223}
182224
183225void GridBase::afterDraw (ax::Node* /* target*/ )
184226{
185227 auto renderer = Director::getInstance ()->getRenderer ();
186228
187- renderer->addCallbackCommand ([renderer, this ]() -> void {
188- const auto & vp = Camera::getDefaultViewport ();
189- renderer->setViewport (vp.x , vp.y , vp.width , vp.height );
190- renderer->setRenderTarget (_oldRenderTarget);
191- });
192-
193- renderer->popGroup ();
229+ if (_renderTexturePass && _renderTexturePass->isActive ())
230+ _renderTexturePass->end ();
194231
195232 renderer->addCallbackCommand ([this ]() -> void { beforeBlit (); });
196233
@@ -199,6 +236,16 @@ void GridBase::afterDraw(ax::Node* /*target*/)
199236 renderer->addCallbackCommand ([this ]() -> void { afterBlit (); });
200237}
201238
239+ void GridBase::setScreenProjectionForBlit (const Mat4* projection, const Vec2& size)
240+ {
241+ _screenProjectionForBlitEnabled = projection && size.width > 0 .0f && size.height > 0 .0f ;
242+ if (_screenProjectionForBlitEnabled)
243+ {
244+ _screenProjectionForBlit = *projection;
245+ _screenProjectionForBlitSize = size;
246+ }
247+ }
248+
202249// implementation of Grid3D
203250
204251Grid3D* Grid3D::create (const Vec2& gridSize)
@@ -305,9 +352,10 @@ void Grid3D::afterBlit()
305352void Grid3D::blit ()
306353{
307354 updateVertexBuffer ();
308- _drawCommand.init (0 , _blendFunc);
355+ _drawCommand.init (GRID_BLIT_ORDER , _blendFunc);
309356 Director::getInstance ()->getRenderer ()->addCommand (&_drawCommand);
310- ax::Mat4 projectionMat = Camera::getVisitingViewProjectionMatrix ();
357+ auto camera = Camera::getVisitingCamera ();
358+ ax::Mat4 projectionMat = camera ? camera->getVisitingViewProjectionMatrix () : Mat4::identity;
311359 auto programState = _drawCommand.unsafePS ();
312360 programState->setUniform (_mvpMatrixLocation, projectionMat.m , sizeof (projectionMat.m ));
313361 programState->setTexture (_textureLocation, 0 , _texture->getRHITexture ());
@@ -446,12 +494,28 @@ void Grid3D::reuse()
446494
447495void Grid3D::updateVertexBuffer ()
448496{
449- size_t numOfPoints = static_cast <size_t >((_gridSize.width + 1 ) * (_gridSize.height + 1 ));
450- auto tempVecPointer = (Vec3*)_vertices;
497+ size_t numOfPoints = static_cast <size_t >((_gridSize.width + 1 ) * (_gridSize.height + 1 ));
498+ auto tempVecPointer = (Vec3*)_vertices;
499+ auto tempOriginalVecPointer = (Vec3*)_originalVertices;
500+ auto tempTexPointer = (Vec2*)_texCoordinates;
451501 for (size_t i = 0 ; i < numOfPoints; ++i)
452502 {
453503 auto offset = i * (sizeof (Vec3) + sizeof (Vec2));
454- memcpy ((char *)_vertexBuffer + offset, &tempVecPointer[i], sizeof (Vec3));
504+ if (_screenProjectionForBlitEnabled)
505+ {
506+ auto vertex =
507+ projectGridVertexToCanvas (_screenProjectionForBlit, tempVecPointer[i], _screenProjectionForBlitSize);
508+ auto texCoord =
509+ projectGridTexCoordToCanvas (_screenProjectionForBlit, tempOriginalVecPointer[i],
510+ _screenProjectionForBlitSize, _isTextureFlipped, tempTexPointer[i]);
511+ memcpy ((char *)_vertexBuffer + offset, &vertex, sizeof (Vec3));
512+ memcpy ((char *)_vertexBuffer + offset + sizeof (Vec3), &texCoord, sizeof (Vec2));
513+ }
514+ else
515+ {
516+ memcpy ((char *)_vertexBuffer + offset, &tempVecPointer[i], sizeof (Vec3));
517+ memcpy ((char *)_vertexBuffer + offset + sizeof (Vec3), &tempTexPointer[i], sizeof (Vec2));
518+ }
455519 }
456520 _drawCommand.updateVertexBuffer (_vertexBuffer,
457521 (unsigned int )(numOfPoints * sizeof (Vec3) + numOfPoints * sizeof (Vec2)));
@@ -561,9 +625,10 @@ TiledGrid3D* TiledGrid3D::create(const Vec2& gridSize, Texture2D* texture, bool
561625void TiledGrid3D::blit ()
562626{
563627 updateVertexBuffer ();
564- _drawCommand.init (0 , _blendFunc);
628+ _drawCommand.init (GRID_BLIT_ORDER , _blendFunc);
565629 Director::getInstance ()->getRenderer ()->addCommand (&_drawCommand);
566- ax::Mat4 projectionMat = Camera::getVisitingViewProjectionMatrix ();
630+ auto camera = Camera::getVisitingCamera ();
631+ ax::Mat4 projectionMat = camera ? camera->getVisitingViewProjectionMatrix () : Mat4::identity;
567632 auto programState = _drawCommand.unsafePS ();
568633 programState->setUniform (_mvpMatrixLocation, projectionMat.m , sizeof (projectionMat.m ));
569634 programState->setTexture (_textureLocation, 0 , _texture->getRHITexture ());
@@ -700,13 +765,29 @@ void TiledGrid3D::reuse()
700765
701766void TiledGrid3D::updateVertexBuffer ()
702767{
703- size_t gradSize = static_cast <size_t >(_gridSize.width * _gridSize.height );
704- size_t numOfPoints = gradSize * 4 ;
705- auto tempVecPointer = (Vec3*)_vertices;
768+ size_t gradSize = static_cast <size_t >(_gridSize.width * _gridSize.height );
769+ size_t numOfPoints = gradSize * 4 ;
770+ auto tempVecPointer = (Vec3*)_vertices;
771+ auto tempOriginalVecPointer = (Vec3*)_originalVertices;
772+ auto tempTexPointer = (Vec2*)_texCoordinates;
706773 for (size_t i = 0 ; i < numOfPoints; ++i)
707774 {
708775 auto offset = i * (sizeof (Vec3) + sizeof (Vec2));
709- memcpy ((char *)_vertexBuffer + offset, &tempVecPointer[i], sizeof (Vec3));
776+ if (_screenProjectionForBlitEnabled)
777+ {
778+ auto vertex =
779+ projectGridVertexToCanvas (_screenProjectionForBlit, tempVecPointer[i], _screenProjectionForBlitSize);
780+ auto texCoord =
781+ projectGridTexCoordToCanvas (_screenProjectionForBlit, tempOriginalVecPointer[i],
782+ _screenProjectionForBlitSize, _isTextureFlipped, tempTexPointer[i]);
783+ memcpy ((char *)_vertexBuffer + offset, &vertex, sizeof (Vec3));
784+ memcpy ((char *)_vertexBuffer + offset + sizeof (Vec3), &texCoord, sizeof (Vec2));
785+ }
786+ else
787+ {
788+ memcpy ((char *)_vertexBuffer + offset, &tempVecPointer[i], sizeof (Vec3));
789+ memcpy ((char *)_vertexBuffer + offset + sizeof (Vec3), &tempTexPointer[i], sizeof (Vec2));
790+ }
710791 }
711792 _drawCommand.updateVertexBuffer (_vertexBuffer,
712793 (unsigned int )(numOfPoints * sizeof (Vec3) + numOfPoints * sizeof (Vec2)));
0 commit comments