Overview

V4 中改变全局状态的唯一途径就是通过 Renderer 对象。如开启深度测试。接下来将逐一分析如何通过 Renderer 设置全局状态及固定管线函数。

clear attachment

通过 ClearFlag 指定需要清空的缓冲区

  1. _renderer->clear(ClearFlag::ALL, // Clear color, depth and stencil buffer.
  2. _clearColor, // the color value used when the color buffer is cleared
  3. 1, // the depth value used when the depth buffer is cleared
  4. 0, // the index used when the stencil buffer is cleared
  5. -10000.0); // specifies the globalOrder value

深度测试

在初始化函数中,设置回调函数,用于保存和恢复原先的全局状态。

  1. void Demo::init()
  2. {
  3. _customCommand.setBeforeCallback(CC_CALLBACK_0(Demo::onBeforeDraw, this));
  4. _customCommand.setAfterCallback(CC_CALLBACK_0(Demo::onAfterDraw, this));
  5. }
  • onBeforeDraw
  1. void Demo::onBeforeDraw()
  2. {
  3. auto renderer = Director::getInstance()->getRenderer();
  4. // manually save the global state
  5. _oldDepthTestEnabled = renderer->getDepthTest();
  6. _oldDepthWriteMask = renderer->getDepthWrite();
  7. _oldDepthCmpFunc = renderer->getDepthCompareFunction();
  8. ... //store other global state, such as cull mode.
  9. renderer->setDepthTest(true);
  10. renderer->setDepthWrite(true);
  11. renderer->setDepthCompareFunction(backend::CompareFunction::LESS_EQUAL);
  12. ... //do additional operations.
  13. }
  • onAfterDraw
  1. void Demo::onAfterDraw()
  2. {
  3. auto renderer = Director::getInstance()->getRenderer();
  4. // manually restore the global state
  5. renderer->setDepthTest(_oldDepthTestEnabled);
  6. renderer->setDepthWrite(_oldDepthWriteMask);
  7. renderer->setDepthCompareFunction(_oldDepthCmpFunc);
  8. ... //restore other global state
  9. }

模板测试

深度测试一样,设置用于保存和恢复原先全局状态的回调函数。

  1. void Demo::init()
  2. {
  3. _customCommand.setBeforeCallback(CC_CALLBACK_0(Demo::onBeforeDraw, this));
  4. _customCommand.setAfterCallback(CC_CALLBACK_0(Demo::onAfterDraw, this));
  5. }
  • onBeforeDraw
  1. void Demo::onBeforeDraw()
  2. {
  3. auto renderer = Director::getInstance()->getRenderer();
  4. // manually save the stencil state
  5. _oldStencilEnabled = renderer->getStencilTest();
  6. _oldStencilWriteMask = renderer->getStencilWriteMask();
  7. _oldStencilFunc = renderer->getStencilCompareFunction();
  8. _oldStencilRef = renderer->getStencilReferenceValue();
  9. _oldStencilReadMask = renderer->getStencilReadMask();
  10. _oldStencilFail = renderer->getStencilFailureOperation();
  11. _oldStencilPassDepthFail = renderer->getStencilPassDepthFailureOperation();
  12. _oldStencilPassDepthPass = renderer->getStencilDepthPassOperation();
  13. ... // save other global states
  14. // set stencil states
  15. renderer->setStencilTest(true);
  16. renderer->setStencilWriteMask(_writeMask);
  17. renderer->setStencilCompareFunction(_compareFunction,
  18. _refValue,
  19. _readMask);
  20. renderer->setStencilOperation(_sfailOp,
  21. _zfailOp,
  22. _zpassOp);
  23. }
  • onAfterDraw
  1. void StencilStateManager::onAfterVisit()
  2. {
  3. // manually restore the stencil state
  4. auto renderer = Director::getInstance()->getRenderer();
  5. renderer->setStencilCompareFunction(_oldStencilFunc,
  6. _oldStencilRef,
  7. _oldStencilReadMask);
  8. renderer->setStencilOperation(_oldFail,
  9. _oldPassDepthFail,
  10. _oldPassDepthPass);
  11. renderer->setStencilWriteMask(_oldStencilWriteMask);
  12. if (!_oldStencilEnabled)
  13. {
  14. renderer->setStencilTest(false);
  15. }
  16. }

Viewport

  1. //保存当前 viewport
  2. _oldViewport = renderer->getViewport();
  3. renderer->setViewPort(viewport.origin.x,
  4. viewport.origin.y,
  5. viewport.size.width,
  6. viewport.size.height);

Scissor

  1. //save scissor test status
  2. _oldScissorTest = renderer->getScissorTest();
  3. _oldScissorRect = renderer->getScissorRect();
  4. //set scissor test
  5. renderer->setScissorTest(true);
  6. renderer->setScissorRect(x, y, width, height);
  7. //restore scissor test status
  8. renderer->setScissorTest(_oldScissorTest);
  9. renderer->setScissorRect(_oldScissorRect.x,
  10. _oldScissorRect.y,
  11. _oldScissorRect.width,
  12. _oldScissorRect.height);

CullMode

  1. _oldCullMode = renderer->getCullMode();
  2. renderer->setCullMode(cullMode);

Winding

  1. _oldWinding = renderer->getWinding();
  2. renderer->setWinding(winding);

Set render target

设置用于保存和恢复 attachment 的回调函数。

  1. void Demo::init()
  2. {
  3. _beginCallbackCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);
  4. _endCallbackCommand.func = CC_CALLBACK_0(RenderTexture::onEnd, this);
  5. }
  • onBegin
  1. //save attachemnt status
  2. _oldColorAttachment = renderer->getColorAttachment();
  3. _oldDepthAttachment = renderer->getDepthAttachment();
  4. _oldStencilAttachment = renderer->getStencilAttachment();
  5. _oldRenderTargetFlag = renderer->getRenderTargetFlag();
  6. renderer->setRenderTarget(_renderTargetFlags, // indicate which attachment to be replaced
  7. _texture2D,
  8. _depthTexture,
  9. _stencilTexture);
  • onEnd
  1. renderer->setRenderTarget(_oldRenderTargetFlag,
  2. _oldColorAttachment,
  3. _oldDepthAttachment,
  4. _oldStencilAttachment);