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);