diff --git a/cocos/3d/CCSprite3D.cpp b/cocos/3d/CCSprite3D.cpp index 0bbc9ccd58..9f3abf342d 100644 --- a/cocos/3d/CCSprite3D.cpp +++ b/cocos/3d/CCSprite3D.cpp @@ -399,4 +399,18 @@ const BlendFunc& Sprite3D::getBlendFunc() const return _blend; } +void Sprite3D::setCullFace(GLenum cullFace) +{ + for (auto& it : _meshCommands) { + it.setCullFace(cullFace); + } +} + +void Sprite3D::setCullFaceEnabled(bool enable) +{ + for (auto& it : _meshCommands) { + it.setCullFaceEnabled(enable); + } +} + NS_CC_END diff --git a/cocos/3d/CCSprite3D.h b/cocos/3d/CCSprite3D.h index 734f52c675..9e79ba37ab 100644 --- a/cocos/3d/CCSprite3D.h +++ b/cocos/3d/CCSprite3D.h @@ -79,6 +79,11 @@ public: // overrides virtual void setBlendFunc(const BlendFunc &blendFunc) override; virtual const BlendFunc &getBlendFunc() const override; + + // set which face is going to cull, GL_BACK, GL_FRONT, GL_FRONT_AND_BACK, default GL_BACK + void setCullFace(GLenum cullFace); + // set cull face enable or not + void setCullFaceEnabled(bool enable); CC_CONSTRUCTOR_ACCESS: diff --git a/cocos/renderer/CCMeshCommand.cpp b/cocos/renderer/CCMeshCommand.cpp index ad251cb9cc..8b69a7c3b0 100644 --- a/cocos/renderer/CCMeshCommand.cpp +++ b/cocos/renderer/CCMeshCommand.cpp @@ -41,6 +41,12 @@ NS_CC_BEGIN +//render state +static bool s_cullFaceEnabled = false; +static GLenum s_cullFace = 0; +static bool s_depthTestEnabled = false; +static bool s_depthWriteEnabled = false; + MeshCommand::MeshCommand() : _textureID(0) , _blendType(BlendFunc::DISABLE) @@ -86,7 +92,7 @@ void MeshCommand::init(float globalOrder, _primitive = primitive; _indexFormat = indexFormat; _indexCount = indexCount; - _mv = mv; + _mv.set(mv); } void MeshCommand::setCullFaceEnabled(bool enable) @@ -124,35 +130,46 @@ MeshCommand::~MeshCommand() void MeshCommand::applyRenderState() { - if (_cullFaceEnabled) + if (_cullFaceEnabled && !s_cullFaceEnabled) { glEnable(GL_CULL_FACE); - glCullFace(_cullFace); + if (s_cullFace != _cullFace) + { + glCullFace(_cullFace); + s_cullFace = _cullFace; + } + s_cullFaceEnabled = true; } - if (_depthTestEnabled) + if (_depthTestEnabled && !s_depthTestEnabled) { glEnable(GL_DEPTH_TEST); + s_depthTestEnabled = true; } - if (_depthWriteEnabled) + if (_depthWriteEnabled && !s_depthWriteEnabled) { glDepthMask(GL_TRUE); + s_depthWriteEnabled = true; } } void MeshCommand::restoreRenderState() { - if (_cullFaceEnabled) + if (s_cullFaceEnabled) { glDisable(GL_CULL_FACE); + s_cullFaceEnabled = false; } - if (_depthTestEnabled) + if (s_depthTestEnabled) { glDisable(GL_DEPTH_TEST); + s_depthTestEnabled = false; } - if (_depthWriteEnabled) + if (s_depthWriteEnabled) { glDepthMask(GL_FALSE); + s_depthWriteEnabled = false; } + s_cullFace = 0; } void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, void* mesh, const BlendFunc& blend) @@ -177,8 +194,6 @@ void MeshCommand::MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform) void MeshCommand::preBatchDraw() { - // set render state - applyRenderState(); // Set material GL::bindTexture2D(_textureID); GL::blendFunc(_blendType.src, _blendType.dst); @@ -198,6 +213,9 @@ void MeshCommand::preBatchDraw() } void MeshCommand::batchDraw() { + // set render state + applyRenderState(); + _glProgramState->setUniformVec4("u_color", _displayColor); if (_matrixPaletteSize && _matrixPalette) diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 7da0226345..345d402967 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -55,7 +55,8 @@ static std::function createFunctions[] = CL(Sprite3DWithSkinOutlineTest), #endif CL(Animate3DTest), - CL(AttachmentTest) + CL(AttachmentTest), + CL(Sprite3DMirrorTest) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -993,3 +994,65 @@ void AttachmentTest::onTouchesEnded(const std::vector& touches, Event* e } _hasWeapon = !_hasWeapon; } + +Sprite3DMirrorTest::Sprite3DMirrorTest() +: _sprite(nullptr) +, _mirrorSprite(nullptr) +{ + auto s = Director::getInstance()->getWinSize(); + addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); +} +std::string Sprite3DMirrorTest::title() const +{ + return "Sprite3D Mirror Test"; +} +std::string Sprite3DMirrorTest::subtitle() const +{ + return ""; +} + +void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) +{ + std::string fileName = "Sprite3DTest/orc.c3b"; + auto sprite = Sprite3D::create(fileName); + sprite->setScale(5); + sprite->setRotation3D(Vec3(0,180,0)); + addChild(sprite); + sprite->setPosition( Vec2( p.x - 80, p.y) ); + + //test attach + auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); + sprite->getAttachNode("Bip001 R Hand")->addChild(sp); + + auto animation = Animation3D::create(fileName); + if (animation) + { + auto animate = Animate3D::create(animation); + + sprite->runAction(RepeatForever::create(animate)); + } + _sprite = sprite; + _hasWeapon = true; + + //create mirror Sprite3D + sprite = Sprite3D::create(fileName); + sprite->setScale(5); + sprite->setScaleX(-5); + sprite->setCullFace(GL_FRONT); + sprite->setRotation3D(Vec3(0,180,0)); + addChild(sprite); + sprite->setPosition( Vec2( p.x + 80, p.y) ); + + //test attach + sp = Sprite3D::create("Sprite3DTest/axe.c3b"); + sprite->getAttachNode("Bip001 R Hand")->addChild(sp); + + animation = Animation3D::create(fileName); + if (animation) + { + auto animate = Animate3D::create(animation); + + sprite->runAction(RepeatForever::create(animate)); + } + _mirrorSprite = sprite; +} diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 0d223fc8b5..e34b31067d 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -244,6 +244,22 @@ protected: cocos2d::Sprite3D* _sprite; }; +class Sprite3DMirrorTest : public Sprite3DTestDemo +{ +public: + CREATE_FUNC(Sprite3DMirrorTest); + Sprite3DMirrorTest(); + virtual std::string title() const override; + virtual std::string subtitle() const override; + + void addNewSpriteWithCoords(Vec2 p); + +protected: + bool _hasWeapon; + cocos2d::Sprite3D* _sprite; + cocos2d::Sprite3D* _mirrorSprite; +}; + class Sprite3DTestScene : public TestScene { public: