Overview
V4 中改变全局状态的唯一途径就是通过 Renderer 对象。如开启深度测试。接下来将逐一分析如何通过 Renderer 设置全局状态及固定管线函数。
clear attachment
通过 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); // specifies the globalOrder value
深度测试
在初始化函数中,设置回调函数,用于保存和恢复原先的全局状态。
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 }
模板测试
与深度测试一样,设置用于保存和恢复原先全局状态的回调函数。
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
//保存当前 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
设置用于保存和恢复 attachment 的回调函数。
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);