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

results matching ""

    No results matching ""