mirror of https://github.com/axmolengine/axmol.git
[bugfix] ClippingNode & CameraBackgroundBrush render order (#19496)
* add groupcommand as a barrier to reorder clipping node renderring * add comments
This commit is contained in:
parent
ac6d3f10f0
commit
475b6e63a5
|
@ -121,9 +121,6 @@ CameraBackgroundDepthBrush* CameraBackgroundDepthBrush::create(float depth)
|
|||
|
||||
bool CameraBackgroundDepthBrush::init()
|
||||
{
|
||||
_beforeCommand.func = CC_CALLBACK_0(CameraBackgroundDepthBrush::onBeforeDraw, this);
|
||||
_afterCommand.func = CC_CALLBACK_0(CameraBackgroundDepthBrush::onAfterDraw, this);
|
||||
|
||||
CC_SAFE_RELEASE_NULL(_programState);
|
||||
_programState = new backend::ProgramState(cameraClear_vert, cameraClear_frag);
|
||||
|
||||
|
@ -135,7 +132,7 @@ bool CameraBackgroundDepthBrush::init()
|
|||
auto &layout = pipelineDescriptor.vertexLayout;
|
||||
|
||||
layout.setAtrribute("a_position", 0, backend::VertexFormat::FLOAT3, offsetof(V3F_C4B_T2F, vertices), false);
|
||||
layout.setAtrribute("a_color", 1, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
|
||||
layout.setAtrribute("a_color", 1, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
|
||||
layout.setAtrribute("a_texCoord", 2, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), true);
|
||||
layout.setLayout(sizeof(_vertices[0]), backend::VertexStepMode::VERTEX);
|
||||
|
||||
|
@ -152,6 +149,8 @@ bool CameraBackgroundDepthBrush::init()
|
|||
_vertices[2].texCoords = Tex2F(1, 1);
|
||||
_vertices[3].texCoords = Tex2F(0, 1);
|
||||
|
||||
_customCommand.setBeforeCallback(CC_CALLBACK_0(CameraBackgroundDepthBrush::onBeforeDraw, this));
|
||||
_customCommand.setAfterCallback(CC_CALLBACK_0(CameraBackgroundDepthBrush::onAfterDraw, this));
|
||||
|
||||
initBuffer();
|
||||
return true;
|
||||
|
@ -169,34 +168,37 @@ void CameraBackgroundDepthBrush::initBuffer()
|
|||
|
||||
void CameraBackgroundDepthBrush::drawBackground(Camera* /*camera*/)
|
||||
{
|
||||
_beforeCommand.init(0.0f);
|
||||
// `clear screen` should be executed before other commands
|
||||
_groupCommand.init(-1.0f);
|
||||
_customCommand.init(0.0f);
|
||||
_afterCommand.init(0.0f);
|
||||
|
||||
auto *renderer = Director::getInstance()->getRenderer();
|
||||
|
||||
auto &pipelineDescriptor = _customCommand.getPipelineDescriptor();
|
||||
auto& blend = pipelineDescriptor.blendDescriptor;
|
||||
blend.writeMask = _clearColor ? backend::ColorWriteMask::ALL : backend::ColorWriteMask::NONE;
|
||||
renderer->addCommand(&_groupCommand);
|
||||
renderer->pushGroup(_groupCommand.getRenderQueueID());
|
||||
|
||||
renderer->setStencilWriteMask(0);
|
||||
renderer->setDepthTest(true);
|
||||
renderer->setDepthCompareFunction(backend::CompareFunction::ALWAYS);
|
||||
auto &pipelineDescriptor = _customCommand.getPipelineDescriptor();
|
||||
auto &blend = pipelineDescriptor.blendDescriptor;
|
||||
blend.writeMask = _clearColor ? backend::ColorWriteMask::ALL : backend::ColorWriteMask::NONE;
|
||||
|
||||
//draw
|
||||
_programState->setUniform(_locDepth, &_depth, sizeof(_depth));
|
||||
|
||||
renderer->addCommand(&_beforeCommand);
|
||||
renderer->addCommand(&_customCommand);
|
||||
renderer->addCommand(&_afterCommand);
|
||||
|
||||
renderer->popGroup();
|
||||
}
|
||||
|
||||
void CameraBackgroundDepthBrush::onBeforeDraw()
|
||||
{
|
||||
auto *renderer = Director::getInstance()->getRenderer();
|
||||
_stateBlock.stencilWriteMask = renderer->getStencilWriteMask();
|
||||
_stateBlock.depthTest = renderer->getDepthTest();
|
||||
_stateBlock.compareFunc = renderer->getDepthCompareFunction();
|
||||
_stateBlock.stencilWriteMask = renderer->getStencilWriteMask();
|
||||
_stateBlock.depthTest = renderer->getDepthTest();
|
||||
_stateBlock.compareFunc = renderer->getDepthCompareFunction();
|
||||
|
||||
renderer->setStencilWriteMask(0);
|
||||
renderer->setDepthTest(true);
|
||||
renderer->setDepthCompareFunction(backend::CompareFunction::ALWAYS);
|
||||
}
|
||||
|
||||
void CameraBackgroundDepthBrush::onAfterDraw()
|
||||
|
@ -229,7 +231,12 @@ bool CameraBackgroundColorBrush::init()
|
|||
|
||||
void CameraBackgroundColorBrush::drawBackground(Camera* camera)
|
||||
{
|
||||
utils::setBlending(BlendFunc::ALPHA_NON_PREMULTIPLIED.src, BlendFunc::ALPHA_NON_PREMULTIPLIED.dst);
|
||||
BlendFunc op = { BlendFunc::ALPHA_NON_PREMULTIPLIED.src, BlendFunc::ALPHA_NON_PREMULTIPLIED.dst };
|
||||
|
||||
auto &blend = _customCommand.getPipelineDescriptor().blendDescriptor;
|
||||
blend.sourceRGBBlendFactor = blend.sourceAlphaBlendFactor = op.src;
|
||||
blend.destinationRGBBlendFactor = blend.destinationAlphaBlendFactor = op.dst;
|
||||
blend.blendEnabled = true;
|
||||
|
||||
CameraBackgroundDepthBrush::drawBackground(camera);
|
||||
}
|
||||
|
@ -313,8 +320,8 @@ CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create(
|
|||
Texture2D::TexParams tRepeatParams;
|
||||
tRepeatParams.magFilter = GL_LINEAR;
|
||||
tRepeatParams.minFilter = GL_LINEAR;
|
||||
tRepeatParams.wrapS = GL_CLAMP_TO_EDGE;
|
||||
tRepeatParams.wrapT = GL_CLAMP_TO_EDGE;
|
||||
tRepeatParams.wrapS = GL_CLAMP_TO_EDGE;
|
||||
tRepeatParams.wrapT = GL_CLAMP_TO_EDGE;
|
||||
texture->setTexParameters(tRepeatParams);
|
||||
|
||||
ret = new (std::nothrow) CameraBackgroundSkyBoxBrush;
|
||||
|
@ -352,10 +359,9 @@ CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create()
|
|||
|
||||
void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
|
||||
{
|
||||
|
||||
_beforeCommand.init(0.0f);
|
||||
// `clear screen` should be executed before other commands
|
||||
_groupCommand.init(-1.0f);
|
||||
_customCommand.init(0.0f);
|
||||
_afterCommand.init(0.0f);
|
||||
|
||||
if (!_actived)
|
||||
return;
|
||||
|
@ -373,9 +379,12 @@ void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
|
|||
|
||||
auto *renderer = Director::getInstance()->getRenderer();
|
||||
|
||||
renderer->addCommand(&_beforeCommand);
|
||||
renderer->addCommand(&_groupCommand);
|
||||
renderer->pushGroup(_groupCommand.getRenderQueueID());
|
||||
|
||||
renderer->addCommand(&_customCommand);
|
||||
renderer->addCommand(&_afterCommand);
|
||||
|
||||
renderer->popGroup();
|
||||
|
||||
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 8);
|
||||
|
||||
|
@ -384,23 +393,22 @@ void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
|
|||
bool CameraBackgroundSkyBoxBrush::init()
|
||||
{
|
||||
|
||||
_beforeCommand.func = CC_CALLBACK_0(CameraBackgroundSkyBoxBrush::onBeforeDraw, this);
|
||||
_afterCommand.func = CC_CALLBACK_0(CameraBackgroundSkyBoxBrush::onAfterDraw, this);
|
||||
|
||||
_customCommand.setBeforeCallback(CC_CALLBACK_0(CameraBackgroundSkyBoxBrush::onBeforeDraw, this));
|
||||
_customCommand.setAfterCallback(CC_CALLBACK_0(CameraBackgroundSkyBoxBrush::onAfterDraw, this));
|
||||
|
||||
CC_SAFE_RELEASE_NULL(_programState);
|
||||
_programState = new backend::ProgramState(CC3D_skybox_vert, CC3D_skybox_frag);
|
||||
_uniformColorLoc = _programState->getUniformLocation("u_color");
|
||||
_uniformCameraRotLoc = _programState->getUniformLocation("u_cameraRot");
|
||||
_uniformEnvLoc = _programState->getUniformLocation("u_Env");
|
||||
_programState = new backend::ProgramState(CC3D_skybox_vert, CC3D_skybox_frag);
|
||||
_uniformColorLoc = _programState->getUniformLocation("u_color");
|
||||
_uniformCameraRotLoc = _programState->getUniformLocation("u_cameraRot");
|
||||
_uniformEnvLoc = _programState->getUniformLocation("u_Env");
|
||||
|
||||
|
||||
auto &pipelineDescriptor = _customCommand.getPipelineDescriptor();
|
||||
auto &layout = pipelineDescriptor.vertexLayout;
|
||||
|
||||
pipelineDescriptor.programState = _programState;
|
||||
auto &pipelineDescriptor = _customCommand.getPipelineDescriptor();
|
||||
auto &layout = pipelineDescriptor.vertexLayout;
|
||||
pipelineDescriptor.programState = _programState;
|
||||
// disable blend
|
||||
pipelineDescriptor.blendDescriptor.blendEnabled = false;
|
||||
pipelineDescriptor.blendDescriptor.blendEnabled = false;
|
||||
|
||||
layout.setAtrribute(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, 0, backend::VertexFormat::FLOAT3, 0, false);
|
||||
layout.setLayout(sizeof(Vec3), backend::VertexStepMode::VERTEX);
|
||||
|
||||
|
@ -422,7 +430,8 @@ void CameraBackgroundSkyBoxBrush::initBuffer()
|
|||
_customCommand.updateVertexBuffer(vexBuf, sizeof(vexBuf));
|
||||
|
||||
// init index buffer object
|
||||
uint16_t idxBuf[] = { 2, 1, 0, 3, 2, 0, // font
|
||||
uint16_t idxBuf[] = {
|
||||
2, 1, 0, 3, 2, 0, // font
|
||||
1, 5, 4, 1, 4, 0, // right
|
||||
4, 5, 6, 4, 6, 7, // back
|
||||
7, 6, 2, 7, 2, 3, // left
|
||||
|
@ -447,12 +456,12 @@ bool CameraBackgroundSkyBoxBrush::isActived() const
|
|||
}
|
||||
void CameraBackgroundSkyBoxBrush::setActived(bool actived)
|
||||
{
|
||||
_actived = actived;
|
||||
_actived = actived;
|
||||
}
|
||||
|
||||
void CameraBackgroundSkyBoxBrush::setTextureValid(bool valid)
|
||||
{
|
||||
_textureValid = valid;
|
||||
_textureValid = valid;
|
||||
}
|
||||
|
||||
bool CameraBackgroundSkyBoxBrush::isValid()
|
||||
|
@ -463,10 +472,10 @@ bool CameraBackgroundSkyBoxBrush::isValid()
|
|||
void CameraBackgroundSkyBoxBrush::onBeforeDraw()
|
||||
{
|
||||
auto *renderer = Director::getInstance()->getRenderer();
|
||||
_stateBlock.depthTest = renderer->getDepthTest();
|
||||
_stateBlock.depthWrite = renderer->getDepthWrite();
|
||||
_stateBlock.depthFunc = renderer->getDepthCompareFunction();
|
||||
_stateBlock.cullMode = renderer->getCullMode();
|
||||
_stateBlock.depthTest = renderer->getDepthTest();
|
||||
_stateBlock.depthWrite = renderer->getDepthWrite();
|
||||
_stateBlock.depthFunc = renderer->getDepthCompareFunction();
|
||||
_stateBlock.cullMode = renderer->getCullMode();
|
||||
}
|
||||
|
||||
void CameraBackgroundSkyBoxBrush::onAfterDraw()
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
THE SOFTWARE.
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef _CCCAMERA_BACKGROUND_BRUSH_H__
|
||||
#define _CCCAMERA_BACKGROUND_BRUSH_H__
|
||||
#pragma once
|
||||
|
||||
#include "base/ccTypes.h"
|
||||
#include "base/CCRef.h"
|
||||
|
@ -32,7 +31,7 @@
|
|||
#include "3d/CCFrustum.h"
|
||||
#include "renderer/CCQuadCommand.h"
|
||||
#include "renderer/CCCustomCommand.h"
|
||||
#include "renderer/CCCallbackCommand.h"
|
||||
#include "renderer/CCGroupCommand.h"
|
||||
#include "renderer/backend/Types.h"
|
||||
#include <vector>
|
||||
|
||||
|
@ -171,8 +170,8 @@ protected:
|
|||
float _depth;
|
||||
backend::UniformLocation _locDepth;
|
||||
CustomCommand _customCommand;
|
||||
CallbackCommand _beforeCommand;
|
||||
CallbackCommand _afterCommand;
|
||||
GroupCommand _groupCommand;
|
||||
|
||||
GLboolean _clearColor;
|
||||
std::vector<V3F_C4B_T2F> _vertices;
|
||||
struct {
|
||||
|
@ -299,8 +298,7 @@ private:
|
|||
bool _textureValid;
|
||||
|
||||
CustomCommand _customCommand;
|
||||
CallbackCommand _beforeCommand;
|
||||
CallbackCommand _afterCommand;
|
||||
GroupCommand _groupCommand;
|
||||
|
||||
backend::UniformLocation _uniformColorLoc;
|
||||
backend::UniformLocation _uniformCameraRotLoc;
|
||||
|
@ -316,4 +314,3 @@ private:
|
|||
|
||||
NS_CC_END
|
||||
|
||||
#endif// _CCCAMERA_BACKGROUND_BRUSH_H__
|
||||
|
|
|
@ -46,7 +46,6 @@ NS_CC_BEGIN
|
|||
|
||||
ClippingNode::ClippingNode()
|
||||
: _stencil(nullptr)
|
||||
, _originStencilProgram(nullptr)
|
||||
, _stencilStateManager(new StencilStateManager())
|
||||
{
|
||||
}
|
||||
|
@ -196,10 +195,10 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
|
|||
|
||||
//Add group command
|
||||
|
||||
_groupCommand.init(_globalZOrder);
|
||||
renderer->addCommand(&_groupCommand);
|
||||
_groupCommandStencil.init(_globalZOrder);
|
||||
renderer->addCommand(&_groupCommandStencil);
|
||||
|
||||
renderer->pushGroup(_groupCommand.getRenderQueueID());
|
||||
renderer->pushGroup(_groupCommandStencil.getRenderQueueID());
|
||||
|
||||
// _beforeVisitCmd.init(_globalZOrder);
|
||||
// _beforeVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
|
||||
|
@ -231,6 +230,14 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
|
|||
int i = 0;
|
||||
bool visibleByCamera = isVisitableByVisitingCamera();
|
||||
|
||||
|
||||
// `_groupCommandChildren` is used as a barrier
|
||||
// to ensure commands above be executed before children nodes
|
||||
_groupCommandChildren.init(_globalZOrder);
|
||||
renderer->addCommand(&_groupCommandChildren);
|
||||
|
||||
renderer->pushGroup(_groupCommandChildren.getRenderQueueID());
|
||||
|
||||
if(!_children.empty())
|
||||
{
|
||||
sortAllChildren();
|
||||
|
@ -256,6 +263,9 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
|
|||
this->draw(renderer, _modelViewTransform, flags);
|
||||
}
|
||||
|
||||
|
||||
renderer->popGroup();
|
||||
|
||||
_afterVisitCmd.init(_globalZOrder);
|
||||
_afterVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencilStateManager);
|
||||
renderer->addCommand(&_afterVisitCmd);
|
||||
|
|
|
@ -154,13 +154,11 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
virtual bool init(Node *stencil);
|
||||
|
||||
protected:
|
||||
Node* _stencil;
|
||||
GLProgram* _originStencilProgram;
|
||||
|
||||
StencilStateManager* _stencilStateManager;
|
||||
Node* _stencil = nullptr;
|
||||
StencilStateManager* _stencilStateManager = nullptr;
|
||||
|
||||
GroupCommand _groupCommand;
|
||||
CallbackCommand _beforeVisitCmd;
|
||||
GroupCommand _groupCommandStencil;
|
||||
GroupCommand _groupCommandChildren;
|
||||
CallbackCommand _afterDrawStencilCmd;
|
||||
CallbackCommand _afterVisitCmd;
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ void StencilStateManager::drawFullScreenQuadClearStencil(float globalZOrder)
|
|||
{
|
||||
_customCommand.init(globalZOrder);
|
||||
Director::getInstance()->getRenderer()->addCommand(&_customCommand);
|
||||
_customCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocaiton, Mat4::IDENTITY.m, sizeof(Mat4::IDENTITY.m));
|
||||
_programState->setUniform(_mvpMatrixLocaiton, Mat4::IDENTITY.m, sizeof(Mat4::IDENTITY.m));
|
||||
}
|
||||
|
||||
|
||||
|
@ -110,70 +110,68 @@ void StencilStateManager::onBeforeVisit(float globalZOrder)
|
|||
// mask of all layers less than or equal to the current (ie: for layer 3: 00000111)
|
||||
_mask_layer_le = mask_layer | mask_layer_l;
|
||||
|
||||
_beforeDrawQuadCmd.init(globalZOrder);
|
||||
_beforeDrawQuadCmd.func = [=]() -> void {
|
||||
|
||||
// manually save the stencil state
|
||||
_currentStencilEnabled = renderer->getStencilTest();
|
||||
_currentStencilWriteMask = renderer->getStencilWriteMask();
|
||||
_currentStencilFunc = renderer->getStencilCompareFunction();
|
||||
_currentStencilRef = renderer->getStencilReferenceValue();
|
||||
_currentStencilReadMask = renderer->getStencilReadMask();
|
||||
_currentStencilFail = renderer->getStencilFailureOperation();
|
||||
_currentStencilPassDepthFail = renderer->getStencilPassDepthFailureOperation();
|
||||
_currentStencilPassDepthPass = renderer->getStencilDepthPassOperation();
|
||||
|
||||
// enable stencil use
|
||||
renderer->setStencilTest(true);
|
||||
|
||||
// all bits on the stencil buffer are readonly, except the current layer bit,
|
||||
// this means that operation like glClear or glStencilOp will be masked with this value
|
||||
renderer->setStencilWriteMask(mask_layer);
|
||||
|
||||
// manually save the depth test state
|
||||
|
||||
_currentDepthWriteMask = renderer->getDepthWrite();
|
||||
|
||||
// disable update to the depth buffer while drawing the stencil,
|
||||
// as the stencil is not meant to be rendered in the real scene,
|
||||
// it should never prevent something else to be drawn,
|
||||
// only disabling depth buffer update should do
|
||||
renderer->setDepthWrite(false);
|
||||
|
||||
///////////////////////////////////
|
||||
// CLEAR STENCIL BUFFER
|
||||
|
||||
// manually clear the stencil buffer by drawing a fullscreen rectangle on it
|
||||
// setup the stencil test func like this:
|
||||
// for each pixel in the fullscreen rectangle
|
||||
// never draw it into the frame buffer
|
||||
// if not in inverted mode: set the current layer value to 0 in the stencil buffer
|
||||
// if in inverted mode: set the current layer value to 1 in the stencil buffer
|
||||
renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, mask_layer, mask_layer);
|
||||
renderer->setStencilOperation(!_inverted ? backend::StencilOperation::ZERO : backend::StencilOperation::REPLACE,
|
||||
backend::StencilOperation::KEEP,
|
||||
backend::StencilOperation::KEEP);
|
||||
};
|
||||
renderer->addCommand(&_beforeDrawQuadCmd);
|
||||
_customCommand.setBeforeCallback(CC_CALLBACK_0(StencilStateManager::onBeforeDrawQuadCmd, this, (int)mask_layer));
|
||||
_customCommand.setAfterCallback(CC_CALLBACK_0(StencilStateManager::onAfterDrawQuadCmd, this, (int)mask_layer));
|
||||
|
||||
// draw a fullscreen solid rectangle to clear the stencil buffer
|
||||
drawFullScreenQuadClearStencil(globalZOrder);
|
||||
|
||||
_afterDrawQuadCmd.init(globalZOrder);
|
||||
_afterDrawQuadCmd.func = [=]() -> void {
|
||||
// setup the stencil test func like this:
|
||||
// for each pixel in the stencil node
|
||||
// never draw it into the frame buffer
|
||||
// if not in inverted mode: set the current layer value to 1 in the stencil buffer
|
||||
// if in inverted mode: set the current layer value to 0 in the stencil buffer
|
||||
auto renderer = Director::getInstance()->getRenderer();
|
||||
renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, mask_layer, mask_layer);
|
||||
}
|
||||
|
||||
renderer->setStencilOperation(!_inverted ? backend::StencilOperation::REPLACE : backend::StencilOperation::ZERO,
|
||||
backend::StencilOperation::KEEP,
|
||||
backend::StencilOperation::KEEP);
|
||||
};
|
||||
renderer->addCommand(&_afterDrawQuadCmd);
|
||||
void StencilStateManager::onBeforeDrawQuadCmd(int mask_layer)
|
||||
{
|
||||
auto renderer = Director::getInstance()->getRenderer();
|
||||
|
||||
// manually save the stencil state
|
||||
_currentStencilEnabled = renderer->getStencilTest();
|
||||
_currentStencilWriteMask = renderer->getStencilWriteMask();
|
||||
_currentStencilFunc = renderer->getStencilCompareFunction();
|
||||
_currentStencilRef = renderer->getStencilReferenceValue();
|
||||
_currentStencilReadMask = renderer->getStencilReadMask();
|
||||
_currentStencilFail = renderer->getStencilFailureOperation();
|
||||
_currentStencilPassDepthFail = renderer->getStencilPassDepthFailureOperation();
|
||||
_currentStencilPassDepthPass = renderer->getStencilDepthPassOperation();
|
||||
|
||||
// enable stencil use
|
||||
renderer->setStencilTest(true);
|
||||
|
||||
// all bits on the stencil buffer are readonly, except the current layer bit,
|
||||
// this means that operation like glClear or glStencilOp will be masked with this value
|
||||
renderer->setStencilWriteMask(mask_layer);
|
||||
|
||||
// manually save the depth test state
|
||||
|
||||
_currentDepthWriteMask = renderer->getDepthWrite();
|
||||
|
||||
// disable update to the depth buffer while drawing the stencil,
|
||||
// as the stencil is not meant to be rendered in the real scene,
|
||||
// it should never prevent something else to be drawn,
|
||||
// only disabling depth buffer update should do
|
||||
renderer->setDepthWrite(false);
|
||||
|
||||
///////////////////////////////////
|
||||
// CLEAR STENCIL BUFFER
|
||||
|
||||
// manually clear the stencil buffer by drawing a fullscreen rectangle on it
|
||||
// setup the stencil test func like this:
|
||||
// for each pixel in the fullscreen rectangle
|
||||
// never draw it into the frame buffer
|
||||
// if not in inverted mode: set the current layer value to 0 in the stencil buffer
|
||||
// if in inverted mode: set the current layer value to 1 in the stencil buffer
|
||||
renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, mask_layer, mask_layer);
|
||||
renderer->setStencilOperation(!_inverted ? backend::StencilOperation::ZERO : backend::StencilOperation::REPLACE,
|
||||
backend::StencilOperation::KEEP,
|
||||
backend::StencilOperation::KEEP);
|
||||
}
|
||||
|
||||
void StencilStateManager::onAfterDrawQuadCmd(int mask_layer)
|
||||
{
|
||||
auto renderer = Director::getInstance()->getRenderer();
|
||||
renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, mask_layer, mask_layer);
|
||||
|
||||
renderer->setStencilOperation(!_inverted ? backend::StencilOperation::REPLACE : backend::StencilOperation::ZERO,
|
||||
backend::StencilOperation::KEEP,
|
||||
backend::StencilOperation::KEEP);
|
||||
}
|
||||
|
||||
void StencilStateManager::onAfterDrawStencil()
|
||||
|
|
|
@ -56,6 +56,8 @@ private:
|
|||
*/
|
||||
void drawFullScreenQuadClearStencil(float globalZOrder);
|
||||
|
||||
void onBeforeDrawQuadCmd(int maskLayer);
|
||||
void onAfterDrawQuadCmd(int maskLayer);
|
||||
|
||||
float _alphaThreshold = 1.f;
|
||||
bool _inverted = false;
|
||||
|
@ -77,8 +79,6 @@ private:
|
|||
unsigned int _mask_layer_le = 0;
|
||||
|
||||
CustomCommand _customCommand;
|
||||
CallbackCommand _beforeDrawQuadCmd;
|
||||
CallbackCommand _afterDrawQuadCmd;
|
||||
CallbackCommand _afterDrawStencilCmd;
|
||||
CallbackCommand _afterVisitCmd;
|
||||
|
||||
|
|
|
@ -62,7 +62,10 @@ public:
|
|||
cases.
|
||||
*/
|
||||
using IndexFormat = backend::IndexFormat;
|
||||
|
||||
|
||||
|
||||
typedef std::function<void()> CallBackFunc;
|
||||
|
||||
/**Constructor.*/
|
||||
CustomCommand();
|
||||
/**Destructor.*/
|
||||
|
@ -192,6 +195,20 @@ public:
|
|||
//TODO:minggo: should remove it.
|
||||
std::function<void()> func;
|
||||
|
||||
/**
|
||||
* set a callback which will be invoke before rendering
|
||||
*/
|
||||
void setBeforeCallback(const CallBackFunc &before) { _beforeCallback = before; }
|
||||
|
||||
/**
|
||||
* set a callback which will be invoke after rendering
|
||||
*/
|
||||
void setAfterCallback(const CallBackFunc &after) { _afterCallback = after; }
|
||||
|
||||
const CallBackFunc &getBeforeCallback() { return _beforeCallback; }
|
||||
|
||||
const CallBackFunc &getAfterCallback() { return _afterCallback; }
|
||||
|
||||
protected:
|
||||
unsigned int computeIndexSize() const;
|
||||
|
||||
|
@ -214,6 +231,10 @@ protected:
|
|||
|
||||
unsigned int _vertexCapacity = 0;
|
||||
unsigned int _indexCapacity = 0;
|
||||
|
||||
|
||||
CallBackFunc _beforeCallback = nullptr;
|
||||
CallBackFunc _afterCallback = nullptr;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _CC_MESHCOMMAND_H_
|
||||
#define _CC_MESHCOMMAND_H_
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include "renderer/CCRenderCommand.h"
|
||||
|
@ -57,8 +56,6 @@ public:
|
|||
*/
|
||||
using IndexFormat = backend::IndexFormat;
|
||||
|
||||
typedef std::function<void()> CallBackFunc;
|
||||
|
||||
MeshCommand();
|
||||
virtual ~MeshCommand();
|
||||
|
||||
|
@ -68,29 +65,11 @@ public:
|
|||
*/
|
||||
void init(float globalZOrder);
|
||||
|
||||
/**
|
||||
* set a callback which will be invoke before rendering
|
||||
*/
|
||||
void setBeforeCallback(const CallBackFunc &before) { _beforeCallback = before; }
|
||||
|
||||
/**
|
||||
* set a callback which will be invoke after rendering
|
||||
*/
|
||||
void setAfterCallback(const CallBackFunc &after){ _afterCallback = after; }
|
||||
|
||||
const CallBackFunc &getBeforeCallback() { return _beforeCallback; }
|
||||
|
||||
const CallBackFunc &getAfterCallback() { return _afterCallback; }
|
||||
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
void listenRendererRecreated(EventCustom* event);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
CallBackFunc _beforeCallback = nullptr;
|
||||
CallBackFunc _afterCallback = nullptr;
|
||||
|
||||
#if CC_ENABLE_CACHE_TEXTURE_DATA
|
||||
EventListenerCustom* _rendererRecreatedListener;
|
||||
#endif
|
||||
|
@ -98,4 +77,3 @@ protected:
|
|||
|
||||
NS_CC_END
|
||||
|
||||
#endif //_CC_MESHCOMMAND_H_
|
||||
|
|
|
@ -642,7 +642,9 @@ void Renderer::drawBatchedTriangles()
|
|||
void Renderer::drawCustomCommand(RenderCommand *command)
|
||||
{
|
||||
auto cmd = static_cast<CustomCommand*>(command);
|
||||
|
||||
|
||||
if (cmd->getBeforeCallback()) cmd->getBeforeCallback()();
|
||||
|
||||
beginRenderPass(command);
|
||||
_commandBuffer->setVertexBuffer(0, cmd->getVertexBuffer());
|
||||
_commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState);
|
||||
|
@ -667,18 +669,14 @@ void Renderer::drawCustomCommand(RenderCommand *command)
|
|||
}
|
||||
_drawnBatches++;
|
||||
_commandBuffer->endRenderPass();
|
||||
|
||||
if (cmd->getAfterCallback()) cmd->getAfterCallback()();
|
||||
}
|
||||
|
||||
void Renderer::drawMeshCommand(RenderCommand *command)
|
||||
{
|
||||
auto cmd = static_cast<MeshCommand*>(command);
|
||||
|
||||
if (cmd->getBeforeCallback()) cmd->getBeforeCallback()();
|
||||
|
||||
//MeshCommand and CustomCommand are identical while rendering.
|
||||
drawCustomCommand(command);
|
||||
|
||||
if (cmd->getAfterCallback()) cmd->getAfterCallback()();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue