Global Status Overview
The only way to change the global state in V4 is through the Renderer
object. For example, turn on the depth test. Next, we will analyze how to set the global state and fixed pipeline functions through the Renderer.
clear attachment
Specify the buffer to be emptied by ClearFlag
_renderer->clear(ClearFlag::ALL, // Clear color, depth and stencil buffer.
_clearColor, // the color value used when the color buffer is cleared
1, // the depth value used when the depth buffer is cleared
0, // the index used when the stencil buffer is cleared
-10000.0); // specify the globalOrder value
Depth Test
In the initialization function, set a callback function to save and restore the original global state.
void Demo::init()
{
_customCommand.setBeforeCallback(CC_CALLBACK_0(Demo::onBeforeDraw, this));
_customCommand.setAfterCallback(CC_CALLBACK_0(Demo::onAfterDraw, this));
}
onBeforeDraw
void Demo::onBeforeDraw() { auto renderer = Director::getInstance()->getRenderer(); // manually save the global state _oldDepthTestEnabled = renderer->getDepthTest(); _oldDepthWriteMask = renderer->getDepthWrite(); _oldDepthCmpFunc = renderer->getDepthCompareFunction(); ... // store other global state, such as cull mode. renderer->setDepthTest(true); renderer->setDepthWrite(true); renderer->setDepthCompareFunction(backend::CompareFunction::LESS_EQUAL); ... //do additional operations. }
onAfterDraw
void Demo::onAfterDraw() { auto renderer = Director::getInstance()->getRenderer(); // manually restore the global state renderer->setDepthTest(_oldDepthTestEnabled); renderer->setDepthWrite(_oldDepthWriteMask); renderer->setDepthCompareFunction(_oldDepthCmpFunc); ...restore other global state }
Stencil Test
As with Depth Test, set the callback function to save and restore the original global state.
void Demo::init()
{
_customCommand.setBeforeCallback(CC_CALLBACK_0(Demo::onBeforeDraw, this));
_customCommand.setAfterCallback(CC_CALLBACK_0(Demo::onAfterDraw, this));
}
onBeforeDraw
void Demo::onBeforeDraw() { auto renderer = Director::getInstance()->getRenderer(); // manually save the stencil state _oldStencilEnabled = renderer->getStencilTest(); _oldStencilWriteMask = renderer->getStencilWriteMask(); _oldStencilFunc = renderer->getStencilCompareFunction(); _oldStencilRef = renderer->getStencilReferenceValue(); _oldStencilReadMask = renderer->getStencilReadMask(); _oldStencilFail = renderer->getStencilFailureOperation(); _oldStencilPassDepthFail = renderer->getStencilPassDepthFailureOperation(); _oldStencilPassDepthPass = renderer->getStencilDepthPassOperation(); ... // save other global states // set stencil states renderer->setStencilTest(true); renderer->setStencilWriteMask(_writeMask); renderer->setStencilCompareFunction(_compareFunction, _refValue, _readMask); renderer->setStencilOperation(_sfailOp, _zfailOp, _zpassOp); }
onAfterDraw
void StencilStateManager::onAfterVisit() { // manually restore the stencil state auto renderer = Director::getInstance()->getRenderer(); renderer->setStencilCompareFunction(_oldStencilFunc, _oldStencilRef, _oldStencilReadMask); renderer->setStencilOperation(_oldFail, _oldPassDepthFail, _oldPassDepthPass); renderer->setStencilWriteMask(_oldStencilWriteMask); if (!_oldStencilEnabled) { renderer->setStencilTest(false); } }
Viewport
// save current viewport
_oldViewport = renderer->getViewport();
renderer->setViewPort(viewport.origin.x,
viewport.origin.y,
viewport.size.width,
viewport.size.height);
Scissor
//save scissor test status
_oldScissorTest = renderer->getScissorTest();
_oldScissorRect = renderer->getScissorRect();
//set scissor test
renderer->setScissorTest(true);
renderer->setScissorRect(x, y, width, height);
//restore scissor test status
renderer->setScissorTest(_oldScissorTest);
renderer->setScissorRect(_oldScissorRect.x,
_oldScissorRect.y,
_oldScissorRect.width,
_oldScissorRect.height);
CullMode
_oldCullMode = renderer->getCullMode();
renderer->setCullMode(cullMode);
Winding
_oldWinding = renderer->getWinding();
renderer->setWinding(winding);
Set render target
Set callbacks to execute some operations before start and after finish rendered to a texture.
void Demo::init()
{
_beginCallbackCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);
_endCallbackCommand.func = CC_CALLBACK_0(RenderTexture::onEnd, this);
}
onBegin
//save attachemnt status _oldColorAttachment = renderer->getColorAttachment(); _oldDepthAttachment = renderer->getDepthAttachment(); _oldStencilAttachment = renderer->getStencilAttachment(); _oldRenderTargetFlag = renderer->getRenderTargetFlag(); renderer->setRenderTarget(_renderTargetFlags, // indicate which attachment to be replaced _texture2D, _depthTexture, _stencilTexture);
onEnd
renderer->setRenderTarget(_oldRenderTargetFlag, _oldColorAttachment, _oldDepthAttachment, _oldStencilAttachment);