mirror of https://github.com/axmolengine/axmol.git
Merge pull request #12324 from ricardoquesada/state_buffer_fixes
State buffer fixes
This commit is contained in:
commit
97c1d29af9
|
@ -33,6 +33,7 @@
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
#include "renderer/ccGLStateCache.h"
|
#include "renderer/ccGLStateCache.h"
|
||||||
#include "renderer/CCFrameBuffer.h"
|
#include "renderer/CCFrameBuffer.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
@ -409,12 +410,20 @@ void Camera::clearBackground(float depth)
|
||||||
{
|
{
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
glStencilMask(0);
|
glStencilMask(0);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilWrite(0);
|
||||||
|
|
||||||
oldDepthTest = glIsEnabled(GL_DEPTH_TEST);
|
oldDepthTest = glIsEnabled(GL_DEPTH_TEST);
|
||||||
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
|
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
|
||||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask);
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthMask);
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(true);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(true);
|
||||||
|
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_ALWAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw
|
//draw
|
||||||
|
@ -461,14 +470,18 @@ void Camera::clearBackground(float depth)
|
||||||
if(GL_FALSE == oldDepthTest)
|
if(GL_FALSE == oldDepthTest)
|
||||||
{
|
{
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(false);
|
||||||
}
|
}
|
||||||
glDepthFunc(oldDepthFunc);
|
glDepthFunc(oldDepthFunc);
|
||||||
if(GL_FALSE == oldDepthMask)
|
if(GL_FALSE == oldDepthMask)
|
||||||
{
|
{
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
glStencilMask(0xFFFFF);
|
glStencilMask(0xFFFFF);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilWrite(0xFFFFF);
|
||||||
|
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
#include "renderer/ccGLStateCache.h"
|
#include "renderer/ccGLStateCache.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
#include "base/CCDirector.h"
|
#include "base/CCDirector.h"
|
||||||
|
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
||||||
|
@ -395,12 +396,15 @@ void ClippingNode::onBeforeVisit()
|
||||||
|
|
||||||
// enable stencil use
|
// enable stencil use
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(true);
|
||||||
|
|
||||||
// check for OpenGL error while enabling stencil test
|
// check for OpenGL error while enabling stencil test
|
||||||
CHECK_GL_ERROR_DEBUG();
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
// all bits on the stencil buffer are readonly, except the current layer bit,
|
// all bits on the stencil buffer are readonly, except the current layer bit,
|
||||||
// this means that operation like glClear or glStencilOp will be masked with this value
|
// this means that operation like glClear or glStencilOp will be masked with this value
|
||||||
glStencilMask(mask_layer);
|
glStencilMask(mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilWrite(mask_layer);
|
||||||
|
|
||||||
// manually save the depth test state
|
// manually save the depth test state
|
||||||
|
|
||||||
|
@ -413,6 +417,7 @@ void ClippingNode::onBeforeVisit()
|
||||||
// it should never prevent something else to be drawn,
|
// it should never prevent something else to be drawn,
|
||||||
// only disabling depth buffer update should do
|
// only disabling depth buffer update should do
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(false);
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
// CLEAR STENCIL BUFFER
|
// CLEAR STENCIL BUFFER
|
||||||
|
@ -424,7 +429,13 @@ void ClippingNode::onBeforeVisit()
|
||||||
// if not in inverted mode: set the current layer value to 0 in the stencil buffer
|
// if not in inverted mode: set the current layer value to 0 in the stencil buffer
|
||||||
// if in inverted mode: set the current layer value to 1 in the stencil buffer
|
// if in inverted mode: set the current layer value to 1 in the stencil buffer
|
||||||
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NEVER, mask_layer, mask_layer);
|
||||||
|
|
||||||
glStencilOp(!_inverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP);
|
glStencilOp(!_inverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
!_inverted ? RenderState::STENCIL_OP_ZERO : RenderState::STENCIL_OP_REPLACE,
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP);
|
||||||
|
|
||||||
// draw a fullscreen solid rectangle to clear the stencil buffer
|
// draw a fullscreen solid rectangle to clear the stencil buffer
|
||||||
//ccDrawSolidRect(Vec2::ZERO, ccpFromSize([[Director sharedDirector] winSize]), Color4F(1, 1, 1, 1));
|
//ccDrawSolidRect(Vec2::ZERO, ccpFromSize([[Director sharedDirector] winSize]), Color4F(1, 1, 1, 1));
|
||||||
|
@ -439,7 +450,14 @@ void ClippingNode::onBeforeVisit()
|
||||||
// if not in inverted mode: set the current layer value to 1 in the stencil buffer
|
// if not in inverted mode: set the current layer value to 1 in the stencil buffer
|
||||||
// if in inverted mode: set the current layer value to 0 in the stencil buffer
|
// if in inverted mode: set the current layer value to 0 in the stencil buffer
|
||||||
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NEVER, mask_layer, mask_layer);
|
||||||
|
|
||||||
glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
|
glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
!_inverted ? RenderState::STENCIL_OP_REPLACE : RenderState::STENCIL_OP_ZERO,
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP);
|
||||||
|
|
||||||
|
|
||||||
// enable alpha test only if the alpha threshold < 1,
|
// enable alpha test only if the alpha threshold < 1,
|
||||||
// indeed if alpha threshold == 1, every pixel will be drawn anyways
|
// indeed if alpha threshold == 1, every pixel will be drawn anyways
|
||||||
|
@ -480,6 +498,8 @@ void ClippingNode::onAfterDrawStencil()
|
||||||
|
|
||||||
// restore the depth test state
|
// restore the depth test state
|
||||||
glDepthMask(_currentDepthWriteMask);
|
glDepthMask(_currentDepthWriteMask);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(_currentDepthWriteMask);
|
||||||
|
|
||||||
//if (currentDepthTestEnabled) {
|
//if (currentDepthTestEnabled) {
|
||||||
// glEnable(GL_DEPTH_TEST);
|
// glEnable(GL_DEPTH_TEST);
|
||||||
//}
|
//}
|
||||||
|
@ -494,7 +514,10 @@ void ClippingNode::onAfterDrawStencil()
|
||||||
// else
|
// else
|
||||||
// do not draw the pixel but keep the current layer in the stencil buffer
|
// do not draw the pixel but keep the current layer in the stencil buffer
|
||||||
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
|
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_EQUAL, _mask_layer_le, _mask_layer_le);
|
||||||
|
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP);
|
||||||
|
|
||||||
// draw (according to the stencil test func) this node and its childs
|
// draw (according to the stencil test func) this node and its childs
|
||||||
}
|
}
|
||||||
|
@ -507,11 +530,18 @@ void ClippingNode::onAfterVisit()
|
||||||
|
|
||||||
// manually restore the stencil state
|
// manually restore the stencil state
|
||||||
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
|
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction((RenderState::StencilFunction)_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
|
||||||
|
|
||||||
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
|
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation((RenderState::StencilOperation)_currentStencilFail,
|
||||||
|
(RenderState::StencilOperation)_currentStencilPassDepthFail,
|
||||||
|
(RenderState::StencilOperation)_currentStencilPassDepthPass);
|
||||||
|
|
||||||
glStencilMask(_currentStencilWriteMask);
|
glStencilMask(_currentStencilWriteMask);
|
||||||
if (!_currentStencilEnabled)
|
if (!_currentStencilEnabled)
|
||||||
{
|
{
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we are done using this layer, decrement
|
// we are done using this layer, decrement
|
||||||
|
|
|
@ -33,6 +33,7 @@ THE SOFTWARE.
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
#include "renderer/ccGLStateCache.h"
|
#include "renderer/ccGLStateCache.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
#include "renderer/CCTexture2D.h"
|
#include "renderer/CCTexture2D.h"
|
||||||
#include "platform/CCGL.h"
|
#include "platform/CCGL.h"
|
||||||
#include "2d/CCCamera.h"
|
#include "2d/CCCamera.h"
|
||||||
|
@ -327,8 +328,12 @@ void Grid3D::beforeBlit()
|
||||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWriteMask);
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWriteMask);
|
||||||
_oldDepthWriteValue = depthWriteMask != GL_FALSE;
|
_oldDepthWriteValue = depthWriteMask != GL_FALSE;
|
||||||
CHECK_GL_ERROR_DEBUG();
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(true);
|
||||||
|
|
||||||
glDepthMask(true);
|
glDepthMask(true);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,8 +345,10 @@ void Grid3D::afterBlit()
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
else
|
else
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(_oldDepthTestValue);
|
||||||
|
|
||||||
glDepthMask(_oldDepthWriteValue);
|
glDepthMask(_oldDepthWriteValue);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(_oldDepthWriteValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
#include "renderer/CCGLProgramState.h"
|
#include "renderer/CCGLProgramState.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
#include "3d/CCSkybox.h"
|
#include "3d/CCSkybox.h"
|
||||||
#include "3d/CCTextureCube.h"
|
#include "3d/CCTextureCube.h"
|
||||||
|
|
||||||
|
@ -183,14 +184,21 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags)
|
||||||
glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
|
glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(true);
|
||||||
|
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_LEQUAL);
|
||||||
|
|
||||||
|
|
||||||
GLboolean cullFlag = glIsEnabled(GL_CULL_FACE);
|
GLboolean cullFlag = glIsEnabled(GL_CULL_FACE);
|
||||||
GLint cullMode;
|
GLint cullMode;
|
||||||
glGetIntegerv(GL_CULL_FACE_MODE, &cullMode);
|
glGetIntegerv(GL_CULL_FACE_MODE, &cullMode);
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
RenderState::StateBlock::_defaultState->setCullFace(true);
|
||||||
|
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
|
RenderState::StateBlock::_defaultState->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
|
||||||
|
|
||||||
if (Configuration::getInstance()->supportsShareableVAO())
|
if (Configuration::getInstance()->supportsShareableVAO())
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "base/CCDirector.h"
|
#include "base/CCDirector.h"
|
||||||
#include "renderer/CCGLProgram.h"
|
#include "renderer/CCGLProgram.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
#include "renderer/ccGLStateCache.h"
|
#include "renderer/ccGLStateCache.h"
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
|
|
||||||
|
@ -131,6 +132,8 @@ void Physics3DDebugDrawer::drawImplementation( const Mat4 &transform, uint32_t f
|
||||||
_program->use();
|
_program->use();
|
||||||
_program->setUniformsForBuiltins(transform);
|
_program->setUniformsForBuiltins(transform);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(true);
|
||||||
|
|
||||||
GL::blendFunc(_blendFunc.src, _blendFunc.dst);
|
GL::blendFunc(_blendFunc.src, _blendFunc.dst);
|
||||||
|
|
||||||
if (_dirty)
|
if (_dirty)
|
||||||
|
@ -158,7 +161,9 @@ void Physics3DDebugDrawer::drawImplementation( const Mat4 &transform, uint32_t f
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCount);
|
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCount);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physics3DDebugDrawer::init()
|
void Physics3DDebugDrawer::init()
|
||||||
|
|
|
@ -37,25 +37,6 @@ NS_CC_BEGIN
|
||||||
|
|
||||||
RenderState::StateBlock* RenderState::StateBlock::_defaultState = nullptr;
|
RenderState::StateBlock* RenderState::StateBlock::_defaultState = nullptr;
|
||||||
|
|
||||||
// Render state override bits
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
RS_BLEND = (1 << 0),
|
|
||||||
RS_BLEND_FUNC = (1 << 1),
|
|
||||||
RS_CULL_FACE = (1 << 2),
|
|
||||||
RS_DEPTH_TEST = (1 << 3),
|
|
||||||
RS_DEPTH_WRITE = (1 << 4),
|
|
||||||
RS_DEPTH_FUNC = (1 << 5),
|
|
||||||
RS_CULL_FACE_SIDE = (1 << 6),
|
|
||||||
RS_STENCIL_TEST = (1 << 7),
|
|
||||||
RS_STENCIL_WRITE = (1 << 8),
|
|
||||||
RS_STENCIL_FUNC = (1 << 9),
|
|
||||||
RS_STENCIL_OP = (1 << 10),
|
|
||||||
RS_FRONT_FACE = (1 << 11),
|
|
||||||
|
|
||||||
RS_ALL_ONES = 0xFFFFFFFF,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
RenderState::RenderState()
|
RenderState::RenderState()
|
||||||
: _texture(nullptr)
|
: _texture(nullptr)
|
||||||
|
@ -731,6 +712,14 @@ uint32_t RenderState::StateBlock::getHash() const
|
||||||
return 0x12345678;
|
return 0x12345678;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderState::StateBlock::invalidate(long stateBits)
|
||||||
|
{
|
||||||
|
CCASSERT(_defaultState, "_default state not created yet. Cannot be invalidated");
|
||||||
|
|
||||||
|
_defaultState->_bits = stateBits;
|
||||||
|
_defaultState->restore(0);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderState::StateBlock::setBlend(bool enabled)
|
void RenderState::StateBlock::setBlend(bool enabled)
|
||||||
{
|
{
|
||||||
_blendEnabled = enabled;
|
_blendEnabled = enabled;
|
||||||
|
|
|
@ -188,7 +188,7 @@ public:
|
||||||
* Defines a block of fixed-function render states that can be applied to a
|
* Defines a block of fixed-function render states that can be applied to a
|
||||||
* RenderState object.
|
* RenderState object.
|
||||||
*/
|
*/
|
||||||
class StateBlock : public Ref
|
class CC_DLL StateBlock : public Ref
|
||||||
{
|
{
|
||||||
friend class RenderState;
|
friend class RenderState;
|
||||||
friend class Pass;
|
friend class Pass;
|
||||||
|
@ -349,6 +349,37 @@ public:
|
||||||
uint32_t getHash() const;
|
uint32_t getHash() const;
|
||||||
bool isDirty() const;
|
bool isDirty() const;
|
||||||
|
|
||||||
|
/** StateBlock bits to be used with invalidate */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RS_BLEND = (1 << 0),
|
||||||
|
RS_BLEND_FUNC = (1 << 1),
|
||||||
|
RS_CULL_FACE = (1 << 2),
|
||||||
|
RS_DEPTH_TEST = (1 << 3),
|
||||||
|
RS_DEPTH_WRITE = (1 << 4),
|
||||||
|
RS_DEPTH_FUNC = (1 << 5),
|
||||||
|
RS_CULL_FACE_SIDE = (1 << 6),
|
||||||
|
RS_STENCIL_TEST = (1 << 7),
|
||||||
|
RS_STENCIL_WRITE = (1 << 8),
|
||||||
|
RS_STENCIL_FUNC = (1 << 9),
|
||||||
|
RS_STENCIL_OP = (1 << 10),
|
||||||
|
RS_FRONT_FACE = (1 << 11),
|
||||||
|
|
||||||
|
RS_ALL_ONES = 0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates the default StateBlock.
|
||||||
|
*
|
||||||
|
* Only call it if you are calling GL calls directly. Invoke this function
|
||||||
|
* at the end of your custom draw call.
|
||||||
|
* This function restores the default render state its defaults values.
|
||||||
|
* Since this function might call GL calls, it must be called in a GL context is present.
|
||||||
|
*
|
||||||
|
* @param stateBits Bitwise-OR of the states that needs to be invalidated
|
||||||
|
*/
|
||||||
|
static void invalidate(long stateBits);
|
||||||
|
|
||||||
static StateBlock* _defaultState;
|
static StateBlock* _defaultState;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -28,6 +28,7 @@ THE SOFTWARE.
|
||||||
#include "renderer/CCGLProgram.h"
|
#include "renderer/CCGLProgram.h"
|
||||||
#include "renderer/CCGLProgramCache.h"
|
#include "renderer/CCGLProgramCache.h"
|
||||||
#include "renderer/ccGLStateCache.h"
|
#include "renderer/ccGLStateCache.h"
|
||||||
|
#include "renderer/CCRenderState.h"
|
||||||
#include "base/CCDirector.h"
|
#include "base/CCDirector.h"
|
||||||
#include "2d/CCDrawingPrimitives.h"
|
#include "2d/CCDrawingPrimitives.h"
|
||||||
#include "renderer/CCRenderer.h"
|
#include "renderer/CCRenderer.h"
|
||||||
|
@ -335,17 +336,43 @@ void Layout::onBeforeVisitStencil()
|
||||||
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
|
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
|
||||||
|
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(true);
|
||||||
|
|
||||||
CHECK_GL_ERROR_DEBUG();
|
CHECK_GL_ERROR_DEBUG();
|
||||||
glStencilMask(mask_layer);
|
glStencilMask(mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilWrite(mask_layer);
|
||||||
|
|
||||||
glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
|
||||||
|
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(false);
|
||||||
|
|
||||||
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(
|
||||||
|
RenderState::STENCIL_NEVER,
|
||||||
|
mask_layer,
|
||||||
|
mask_layer);
|
||||||
|
|
||||||
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
RenderState::STENCIL_OP_ZERO,
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP);
|
||||||
|
|
||||||
|
|
||||||
this->drawFullScreenQuadClearStencil();
|
this->drawFullScreenQuadClearStencil();
|
||||||
|
|
||||||
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(
|
||||||
|
RenderState::STENCIL_NEVER,
|
||||||
|
mask_layer,
|
||||||
|
mask_layer);
|
||||||
|
|
||||||
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
RenderState::STENCIL_OP_REPLACE,
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layout::drawFullScreenQuadClearStencil()
|
void Layout::drawFullScreenQuadClearStencil()
|
||||||
|
@ -392,19 +419,42 @@ void Layout::drawFullScreenQuadClearStencil()
|
||||||
void Layout::onAfterDrawStencil()
|
void Layout::onAfterDrawStencil()
|
||||||
{
|
{
|
||||||
glDepthMask(_currentDepthWriteMask);
|
glDepthMask(_currentDepthWriteMask);
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthWrite(_currentDepthWriteMask);
|
||||||
|
|
||||||
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
|
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(
|
||||||
|
RenderState::STENCIL_EQUAL,
|
||||||
|
_mask_layer_le,
|
||||||
|
_mask_layer_le);
|
||||||
|
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP,
|
||||||
|
RenderState::STENCIL_OP_KEEP);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Layout::onAfterVisitStencil()
|
void Layout::onAfterVisitStencil()
|
||||||
{
|
{
|
||||||
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
|
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(
|
||||||
|
(RenderState::StencilFunction)_currentStencilFunc,
|
||||||
|
_currentStencilRef,
|
||||||
|
_currentStencilValueMask);
|
||||||
|
|
||||||
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
|
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(
|
||||||
|
(RenderState::StencilOperation)_currentStencilFail,
|
||||||
|
(RenderState::StencilOperation)_currentStencilPassDepthFail,
|
||||||
|
(RenderState::StencilOperation)_currentStencilPassDepthPass);
|
||||||
|
|
||||||
glStencilMask(_currentStencilWriteMask);
|
glStencilMask(_currentStencilWriteMask);
|
||||||
if (!_currentStencilEnabled)
|
if (!_currentStencilEnabled)
|
||||||
{
|
{
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(false);
|
||||||
}
|
}
|
||||||
s_layer--;
|
s_layer--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "MaterialSystemTest.h"
|
#include "MaterialSystemTest.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <spine/spine-cocos2dx.h>
|
||||||
|
|
||||||
#include "../testResource.h"
|
#include "../testResource.h"
|
||||||
#include "cocos2d.h"
|
#include "cocos2d.h"
|
||||||
|
@ -47,6 +48,7 @@ MaterialSystemTest::MaterialSystemTest()
|
||||||
ADD_TEST_CASE(Material_MultipleSprite3D);
|
ADD_TEST_CASE(Material_MultipleSprite3D);
|
||||||
ADD_TEST_CASE(Material_Sprite3DTest);
|
ADD_TEST_CASE(Material_Sprite3DTest);
|
||||||
ADD_TEST_CASE(Material_parsePerformance);
|
ADD_TEST_CASE(Material_parsePerformance);
|
||||||
|
ADD_TEST_CASE(Material_invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MaterialSystemBaseTest::title() const
|
std::string MaterialSystemBaseTest::title() const
|
||||||
|
@ -380,6 +382,74 @@ std::string Material_parsePerformance::subtitle() const
|
||||||
{
|
{
|
||||||
return "Testing parsing performance";
|
return "Testing parsing performance";
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
void Material_invalidate::onEnter()
|
||||||
|
{
|
||||||
|
MaterialSystemBaseTest::onEnter();
|
||||||
|
|
||||||
|
// ORC
|
||||||
|
auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b");
|
||||||
|
sprite->setScale(5);
|
||||||
|
sprite->setRotation3D(Vec3(0,180,0));
|
||||||
|
addChild(sprite);
|
||||||
|
sprite->setNormalizedPosition(Vec2(0.3,0.3));
|
||||||
|
|
||||||
|
auto rotate = RotateBy::create(5, Vec3(0,360,0));
|
||||||
|
auto repeat = RepeatForever::create(rotate);
|
||||||
|
sprite->runAction(repeat);
|
||||||
|
|
||||||
|
// SPINE
|
||||||
|
auto skeletonNode = spine::SkeletonAnimation::createWithFile("spine/goblins-ffd.json", "spine/goblins-ffd.atlas", 1.5f);
|
||||||
|
skeletonNode->setAnimation(0, "walk", true);
|
||||||
|
skeletonNode->setSkin("goblin");
|
||||||
|
|
||||||
|
skeletonNode->setScale(0.25);
|
||||||
|
skeletonNode->setNormalizedPosition(Vec2(0.6,0.3));
|
||||||
|
this->addChild(skeletonNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Material_invalidate::subtitle() const
|
||||||
|
{
|
||||||
|
return "Testing RenderState::StateBlock::invalidate()";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Material_invalidate::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
|
||||||
|
{
|
||||||
|
_customCommand.init(_globalZOrder, transform, flags);
|
||||||
|
_customCommand.func = []() {
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
glDepthMask(false);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
glCullFace((GLenum)GL_FRONT);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
glFrontFace((GLenum)GL_CW);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
CHECK_GL_ERROR_DEBUG();
|
||||||
|
|
||||||
|
// a non-optimal way is to pass all bits, but that would be very inefficient
|
||||||
|
// RenderState::StateBlock::invalidate(RenderState::StateBlock::RS_ALL_ONES);
|
||||||
|
|
||||||
|
RenderState::StateBlock::invalidate(RenderState::StateBlock::RS_DEPTH_TEST |
|
||||||
|
RenderState::StateBlock::RS_DEPTH_WRITE |
|
||||||
|
RenderState::StateBlock::RS_CULL_FACE |
|
||||||
|
RenderState::StateBlock::RS_CULL_FACE_SIDE |
|
||||||
|
RenderState::StateBlock::RS_FRONT_FACE |
|
||||||
|
RenderState::StateBlock::RS_BLEND);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer->addCommand(&_customCommand);
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Helper functions
|
// MARK: Helper functions
|
||||||
|
|
||||||
|
|
|
@ -111,4 +111,17 @@ public:
|
||||||
virtual std::string subtitle() const override;
|
virtual std::string subtitle() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Material_invalidate : public MaterialSystemBaseTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CREATE_FUNC(Material_invalidate);
|
||||||
|
|
||||||
|
virtual void onEnter() override;
|
||||||
|
virtual std::string subtitle() const override;
|
||||||
|
|
||||||
|
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
|
||||||
|
|
||||||
|
cocos2d::CustomCommand _customCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,10 @@ void RenderTextureTestDepthStencil::draw(Renderer *renderer, const Mat4 &transfo
|
||||||
void RenderTextureTestDepthStencil::onBeforeClear()
|
void RenderTextureTestDepthStencil::onBeforeClear()
|
||||||
{
|
{
|
||||||
glStencilMask(0xFF);
|
glStencilMask(0xFF);
|
||||||
|
|
||||||
|
// Since cocos2d-x v3.7, users should avoid calling GL directly because it will break the internal GL state
|
||||||
|
// But if users must call GL directly, they should update the state manually,
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilWrite(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderTextureTestDepthStencil::onBeforeStencil()
|
void RenderTextureTestDepthStencil::onBeforeStencil()
|
||||||
|
@ -471,16 +475,30 @@ void RenderTextureTestDepthStencil::onBeforeStencil()
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
glStencilFunc(GL_NEVER, 1, 0xFF);
|
glStencilFunc(GL_NEVER, 1, 0xFF);
|
||||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||||
|
|
||||||
|
// Since cocos2d-x v3.7, users should avoid calling GL directly because it will break the internal GL state
|
||||||
|
// But if users must call GL directly, they should update the state manually,
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(true);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NEVER, 1, 0xFF);
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilOperation(RenderState::STENCIL_OP_REPLACE, RenderState::STENCIL_OP_REPLACE, RenderState::STENCIL_OP_REPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderTextureTestDepthStencil::onBeforDraw()
|
void RenderTextureTestDepthStencil::onBeforDraw()
|
||||||
{
|
{
|
||||||
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||||
|
|
||||||
|
// Since cocos2d-x v3.7, users should avoid calling GL directly because it will break the internal GL state
|
||||||
|
// But if users must call GL directly, they should update the state manually,
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NOTEQUAL, 1, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderTextureTestDepthStencil::onAfterDraw()
|
void RenderTextureTestDepthStencil::onAfterDraw()
|
||||||
{
|
{
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
|
// Since cocos2d-x v3.7, users should avoid calling GL directly because it will break the internal GL state
|
||||||
|
// But if users must call GL directly, they should update the state manually,
|
||||||
|
RenderState::StateBlock::_defaultState->setStencilTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RenderTextureTestDepthStencil::title() const
|
std::string RenderTextureTestDepthStencil::title() const
|
||||||
|
|
|
@ -1054,9 +1054,16 @@ void Effect3DOutline::draw(const Mat4 &transform)
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
// Since cocos2d-x v3.7, users should avoid calling GL directly because it will break the internal GL state
|
||||||
|
// But if users must call GL directly, they should update the state manually,
|
||||||
|
RenderState::StateBlock::_defaultState->setDepthTest(false);
|
||||||
|
RenderState::StateBlock::_defaultState->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
|
||||||
|
RenderState::StateBlock::_defaultState->setCullFace(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue