• Overview
  • clear attachment
  • 深度测试
  • 模板测试
  • Viewport
  • Scissor
  • CullMode
  • Winding
  • Set render target

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