Merge pull request #14470 from zilongshanren/fixListViewClippingIssue

Fix list view clipping issue
This commit is contained in:
zilongshanren 2015-11-26 13:51:51 +08:00
commit c3604aa865
18 changed files with 480 additions and 483 deletions

View File

@ -1234,6 +1234,11 @@
2980F02B1BA9A5550059E678 /* UITextView+CCUITextInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 2980F0201BA9A5550059E678 /* UITextView+CCUITextInput.h */; };
2980F02C1BA9A5550059E678 /* UITextView+CCUITextInput.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2980F0211BA9A5550059E678 /* UITextView+CCUITextInput.mm */; };
2986667F18B1B246000E39CA /* CCTweenFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2986667818B1B079000E39CA /* CCTweenFunction.cpp */; };
298C75D51C0465D0006BAE63 /* CCStencilStateManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 298C75D31C0465D0006BAE63 /* CCStencilStateManager.cpp */; };
298C75D61C0465D1006BAE63 /* CCStencilStateManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 298C75D31C0465D0006BAE63 /* CCStencilStateManager.cpp */; };
298C75D71C0465D1006BAE63 /* CCStencilStateManager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 298C75D41C0465D0006BAE63 /* CCStencilStateManager.hpp */; };
298C75D81C0465D1006BAE63 /* CCStencilStateManager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 298C75D41C0465D0006BAE63 /* CCStencilStateManager.hpp */; };
298C75D91C04681F006BAE63 /* CCStencilStateManager.hpp in Sources */ = {isa = PBXBuildFile; fileRef = 298C75D41C0465D0006BAE63 /* CCStencilStateManager.hpp */; };
299754F4193EC95400A54AC3 /* ObjectFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 299754F2193EC95400A54AC3 /* ObjectFactory.cpp */; };
299754F5193EC95400A54AC3 /* ObjectFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 299754F2193EC95400A54AC3 /* ObjectFactory.cpp */; };
299754F6193EC95400A54AC3 /* ObjectFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 299754F3193EC95400A54AC3 /* ObjectFactory.h */; };
@ -2072,10 +2077,10 @@
B5668D7E1B3838E4003CBD5E /* UIScrollViewBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5668D7B1B3838E4003CBD5E /* UIScrollViewBar.cpp */; };
B5668D7F1B3838E4003CBD5E /* UIScrollViewBar.h in Headers */ = {isa = PBXBuildFile; fileRef = B5668D7C1B3838E4003CBD5E /* UIScrollViewBar.h */; };
B5668D801B3838E4003CBD5E /* UIScrollViewBar.h in Headers */ = {isa = PBXBuildFile; fileRef = B5668D7C1B3838E4003CBD5E /* UIScrollViewBar.h */; };
B5A738961BB0051F00BAAEF8 /* UIPageViewIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A738941BB0051F00BAAEF8 /* UIPageViewIndicator.cpp */; settings = {ASSET_TAGS = (); }; };
B5A738971BB0051F00BAAEF8 /* UIPageViewIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A738941BB0051F00BAAEF8 /* UIPageViewIndicator.cpp */; settings = {ASSET_TAGS = (); }; };
B5A738981BB0051F00BAAEF8 /* UIPageViewIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A738951BB0051F00BAAEF8 /* UIPageViewIndicator.h */; settings = {ASSET_TAGS = (); }; };
B5A738991BB0051F00BAAEF8 /* UIPageViewIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A738951BB0051F00BAAEF8 /* UIPageViewIndicator.h */; settings = {ASSET_TAGS = (); }; };
B5A738961BB0051F00BAAEF8 /* UIPageViewIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A738941BB0051F00BAAEF8 /* UIPageViewIndicator.cpp */; };
B5A738971BB0051F00BAAEF8 /* UIPageViewIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A738941BB0051F00BAAEF8 /* UIPageViewIndicator.cpp */; };
B5A738981BB0051F00BAAEF8 /* UIPageViewIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A738951BB0051F00BAAEF8 /* UIPageViewIndicator.h */; };
B5A738991BB0051F00BAAEF8 /* UIPageViewIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A738951BB0051F00BAAEF8 /* UIPageViewIndicator.h */; };
B5CE6DBE1B3BF2B1002B0419 /* UIAbstractCheckButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5CE6DBC1B3BF2B1002B0419 /* UIAbstractCheckButton.cpp */; };
B5CE6DBF1B3BF2B1002B0419 /* UIAbstractCheckButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5CE6DBC1B3BF2B1002B0419 /* UIAbstractCheckButton.cpp */; };
B5CE6DC01B3BF2B1002B0419 /* UIAbstractCheckButton.h in Headers */ = {isa = PBXBuildFile; fileRef = B5CE6DBD1B3BF2B1002B0419 /* UIAbstractCheckButton.h */; };
@ -4144,6 +4149,8 @@
2980F0211BA9A5550059E678 /* UITextView+CCUITextInput.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UITextView+CCUITextInput.mm"; sourceTree = "<group>"; };
2986667818B1B079000E39CA /* CCTweenFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTweenFunction.cpp; sourceTree = "<group>"; };
2986667918B1B079000E39CA /* CCTweenFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTweenFunction.h; sourceTree = "<group>"; };
298C75D31C0465D0006BAE63 /* CCStencilStateManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCStencilStateManager.cpp; path = ../base/CCStencilStateManager.cpp; sourceTree = "<group>"; };
298C75D41C0465D0006BAE63 /* CCStencilStateManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CCStencilStateManager.hpp; path = ../base/CCStencilStateManager.hpp; sourceTree = "<group>"; };
299754F2193EC95400A54AC3 /* ObjectFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectFactory.cpp; path = ../base/ObjectFactory.cpp; sourceTree = "<group>"; };
299754F3193EC95400A54AC3 /* ObjectFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjectFactory.h; path = ../base/ObjectFactory.h; sourceTree = "<group>"; };
299CF1F919A434BC00C378C1 /* ccRandom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ccRandom.cpp; path = ../base/ccRandom.cpp; sourceTree = "<group>"; };
@ -6037,6 +6044,8 @@
50ABBE1C1925AB6F00A911A9 /* utlist.h */,
50ABBE1D1925AB6F00A911A9 /* ZipUtils.cpp */,
50ABBE1E1925AB6F00A911A9 /* ZipUtils.h */,
298C75D31C0465D0006BAE63 /* CCStencilStateManager.cpp */,
298C75D41C0465D0006BAE63 /* CCStencilStateManager.hpp */,
);
name = base;
path = ../cocos/2d;
@ -9229,6 +9238,7 @@
15AE182A19AAD2F700C27E9E /* CCMeshSkin.h in Headers */,
B276EF5F1988D1D500CD400F /* CCVertexIndexData.h in Headers */,
1A57007F180BC5A10088DEC7 /* CCActionInterval.h in Headers */,
298C75D71C0465D1006BAE63 /* CCStencilStateManager.hpp in Headers */,
B6DD2FDB1B04825B00E47F5F /* DetourLocalBoundary.h in Headers */,
B6CAB3491AF9AA1A00B9B856 /* gim_clip_polygon.h in Headers */,
B677B0DB1B18492D006762CB /* CCNavMeshUtils.h in Headers */,
@ -10669,6 +10679,7 @@
85505F051B60E3B2003F2CD4 /* CCBoneNode.h in Headers */,
B665E2491AA80A6500DDB1C5 /* CCPUCollisionAvoidanceAffectorTranslator.h in Headers */,
B6CAB4461AF9AA1A00B9B856 /* btParallelConstraintSolver.h in Headers */,
298C75D81C0465D1006BAE63 /* CCStencilStateManager.hpp in Headers */,
15AE18D119AAD33D00C27E9E /* CCNodeLoaderLibrary.h in Headers */,
15AE1AC319AAD40300C27E9E /* b2DistanceJoint.h in Headers */,
B6CAB5261AF9AA1A00B9B856 /* btQuickprof.h in Headers */,
@ -11830,6 +11841,7 @@
B665E2EE1AA80A6500DDB1C5 /* CCPULineEmitter.cpp in Sources */,
B6CAB2DD1AF9AA1A00B9B856 /* btScaledBvhTriangleMeshShape.cpp in Sources */,
B665E4121AA80A6600DDB1C5 /* CCPUTextureAnimator.cpp in Sources */,
298C75D51C0465D0006BAE63 /* CCStencilStateManager.cpp in Sources */,
B665E3D21AA80A6600DDB1C5 /* CCPUScriptLexer.cpp in Sources */,
B665E4021AA80A6600DDB1C5 /* CCPUSphereColliderTranslator.cpp in Sources */,
15AE1A3619AAD3D500C27E9E /* b2PolygonShape.cpp in Sources */,
@ -11964,6 +11976,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
298C75D91C04681F006BAE63 /* CCStencilStateManager.hpp in Sources */,
D0FD03541A3B51AA00825BB5 /* CCAllocatorGlobalNewDelete.cpp in Sources */,
15AE1B9819AADAA100C27E9E /* UIVideoPlayer-ios.mm in Sources */,
B665E38F1AA80A6500DDB1C5 /* CCPUPlaneCollider.cpp in Sources */,
@ -12114,6 +12127,7 @@
15AE193C19AAD35100C27E9E /* CCArmatureDefine.cpp in Sources */,
B665E35F1AA80A6500DDB1C5 /* CCPUOnRandomObserverTranslator.cpp in Sources */,
B29594B51926D5EC003EEF37 /* CCMeshCommand.cpp in Sources */,
298C75D61C0465D1006BAE63 /* CCStencilStateManager.cpp in Sources */,
15AE194B19AAD35100C27E9E /* CCComRender.cpp in Sources */,
382384451A25915C002C4610 /* SpriteReader.cpp in Sources */,
B6CAB2321AF9AA1A00B9B856 /* btCollisionWorld.cpp in Sources */,

View File

@ -32,6 +32,7 @@
#include "renderer/CCRenderer.h"
#include "renderer/CCRenderState.h"
#include "base/CCDirector.h"
#include "base/CCStencilStateManager.hpp"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
#define CC_CLIPPING_NODE_OPENGLES 0
@ -41,12 +42,6 @@
NS_CC_BEGIN
static GLint g_sStencilBits = -1;
// store the current stencil layer (position in the stencil buffer),
// this will allow nesting up to n ClippingNode,
// where n is the number of bits of the stencil buffer.
static GLint s_layer = -1;
#if CC_CLIPPING_NODE_OPENGLES
static void setProgram(Node *n, GLProgram *p)
{
@ -61,22 +56,8 @@ static void setProgram(Node *n, GLProgram *p)
ClippingNode::ClippingNode()
: _stencil(nullptr)
, _alphaThreshold(0.0f)
, _inverted(false)
, _currentStencilEnabled(GL_FALSE)
, _currentStencilWriteMask(~0)
, _currentStencilFunc(GL_ALWAYS)
, _currentStencilRef(0)
, _currentStencilValueMask(~0)
, _currentStencilFail(GL_KEEP)
, _currentStencilPassDepthFail(GL_KEEP)
, _currentStencilPassDepthPass(GL_KEEP)
, _currentDepthWriteMask(GL_TRUE)
, _currentAlphaTestEnabled(GL_FALSE)
, _currentAlphaTestFunc(GL_ALWAYS)
, _currentAlphaTestRef(1)
,_stencilStateManager(new StencilStateManager())
{
}
ClippingNode::~ClippingNode()
@ -128,21 +109,6 @@ bool ClippingNode::init(Node *stencil)
CC_SAFE_RELEASE(_stencil);
_stencil = stencil;
CC_SAFE_RETAIN(_stencil);
_alphaThreshold = 1;
_inverted = false;
// get (only once) the number of bits of the stencil buffer
static bool once = true;
if (once)
{
glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits);
if (g_sStencilBits <= 0)
{
CCLOG("Stencil buffer is not enabled.");
}
once = false;
}
return true;
}
@ -222,45 +188,6 @@ void ClippingNode::onExit()
Node::onExit();
}
void ClippingNode::drawFullScreenQuadClearStencil()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when setting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Vec2 vertices[] = {
Vec2(-1.0f, -1.0f),
Vec2(1.0f, -1.0f),
Vec2(1.0f, 1.0f),
Vec2(-1.0f, 1.0f)
};
auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_U_COLOR);
int colorLocation = glProgram->getUniformLocation("u_color");
CHECK_GL_ERROR_DEBUG();
Color4F color(1, 1, 1, 1);
glProgram->use();
glProgram->setUniformsForBuiltins();
glProgram->setUniformLocationWith4fv(colorLocation, (GLfloat*) &color.r, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 4);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
@ -285,9 +212,11 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
renderer->pushGroup(_groupCommand.getRenderQueueID());
_beforeVisitCmd.init(_globalZOrder);
_beforeVisitCmd.func = CC_CALLBACK_0(ClippingNode::onBeforeVisit, this);
_beforeVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
renderer->addCommand(&_beforeVisitCmd);
if (_alphaThreshold < 1)
auto alphaThreshold = this->getAlphaThreshold();
if (alphaThreshold < 1)
{
#if CC_CLIPPING_NODE_OPENGLES
// since glAlphaTest do not exists in OES, use a shader that writes
@ -296,7 +225,7 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
// set our alphaThreshold
program->use();
program->setUniformLocationWith1f(alphaValueLocation, _alphaThreshold);
program->setUniformLocationWith1f(alphaValueLocation, alphaThreshold);
// we need to recursively apply this shader to all the nodes in the stencil node
// FIXME: we should have a way to apply shader to all nodes without having to do this
setProgram(_stencil, program);
@ -307,7 +236,7 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
_stencil->visit(renderer, _modelViewTransform, flags);
_afterDrawStencilCmd.init(_globalZOrder);
_afterDrawStencilCmd.func = CC_CALLBACK_0(ClippingNode::onAfterDrawStencil, this);
_afterDrawStencilCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterDrawStencil, _stencilStateManager);
renderer->addCommand(&_afterDrawStencilCmd);
int i = 0;
@ -339,7 +268,7 @@ void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32
}
_afterVisitCmd.init(_globalZOrder);
_afterVisitCmd.func = CC_CALLBACK_0(ClippingNode::onAfterVisit, this);
_afterVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencilStateManager);
renderer->addCommand(&_afterVisitCmd);
renderer->popGroup();
@ -374,196 +303,23 @@ bool ClippingNode::hasContent() const
GLfloat ClippingNode::getAlphaThreshold() const
{
return _alphaThreshold;
return _stencilStateManager->getAlphaThreshold();
}
void ClippingNode::setAlphaThreshold(GLfloat alphaThreshold)
{
_alphaThreshold = alphaThreshold;
_stencilStateManager->setAlphaThreshold(alphaThreshold);
}
bool ClippingNode::isInverted() const
{
return _inverted;
return _stencilStateManager->isInverted();
}
void ClippingNode::setInverted(bool inverted)
{
_inverted = inverted;
_stencilStateManager->setInverted(inverted);
}
void ClippingNode::onBeforeVisit()
{
///////////////////////////////////
// INIT
// increment the current layer
s_layer++;
// mask of the current layer (ie: for layer 3: 00000100)
GLint mask_layer = 0x1 << s_layer;
// mask of all layers less than the current (ie: for layer 3: 00000011)
GLint mask_layer_l = mask_layer - 1;
// mask of all layers less than or equal to the current (ie: for layer 3: 00000111)
_mask_layer_le = mask_layer | mask_layer_l;
// manually save the stencil state
_currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&_currentStencilWriteMask);
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&_currentStencilFunc);
glGetIntegerv(GL_STENCIL_REF, &_currentStencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&_currentStencilValueMask);
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&_currentStencilFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&_currentStencilPassDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
// enable stencil use
glEnable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(true);
// check for OpenGL error while enabling stencil test
CHECK_GL_ERROR_DEBUG();
// 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
glStencilMask(mask_layer);
// RenderState::StateBlock::_defaultState->setStencilWrite(mask_layer);
// manually save the depth test state
glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
// disable depth test while drawing the stencil
//glDisable(GL_DEPTH_TEST);
// 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
glDepthMask(GL_FALSE);
RenderState::StateBlock::_defaultState->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
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(!_inverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP);
// draw a fullscreen solid rectangle to clear the stencil buffer
//ccDrawSolidRect(Vec2::ZERO, ccpFromSize([[Director sharedDirector] winSize]), Color4F(1, 1, 1, 1));
drawFullScreenQuadClearStencil();
///////////////////////////////////
// DRAW CLIPPING STENCIL
// 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
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
// RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NEVER, mask_layer, mask_layer);
glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(
// !_inverted ? RenderState::STENCIL_OP_REPLACE : RenderState::STENCIL_OP_ZERO,
// RenderState::STENCIL_OP_KEEP,
// RenderState::STENCIL_OP_KEEP);
// enable alpha test only if the alpha threshold < 1,
// indeed if alpha threshold == 1, every pixel will be drawn anyways
if (_alphaThreshold < 1) {
#if !CC_CLIPPING_NODE_OPENGLES
// manually save the alpha test state
_currentAlphaTestEnabled = glIsEnabled(GL_ALPHA_TEST);
glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint *)&_currentAlphaTestFunc);
glGetFloatv(GL_ALPHA_TEST_REF, &_currentAlphaTestRef);
// enable alpha testing
glEnable(GL_ALPHA_TEST);
// check for OpenGL error while enabling alpha test
CHECK_GL_ERROR_DEBUG();
// pixel will be drawn only if greater than an alpha threshold
glAlphaFunc(GL_GREATER, _alphaThreshold);
#endif
}
//Draw _stencil
}
void ClippingNode::onAfterDrawStencil()
{
// restore alpha test state
if (_alphaThreshold < 1)
{
#if CC_CLIPPING_NODE_OPENGLES
// FIXME: we need to find a way to restore the shaders of the stencil node and its children
#else
// manually restore the alpha test state
glAlphaFunc(_currentAlphaTestFunc, _currentAlphaTestRef);
if (!_currentAlphaTestEnabled)
{
glDisable(GL_ALPHA_TEST);
}
#endif
}
// restore the depth test state
glDepthMask(_currentDepthWriteMask);
RenderState::StateBlock::_defaultState->setDepthWrite(_currentDepthWriteMask != 0);
//if (currentDepthTestEnabled) {
// glEnable(GL_DEPTH_TEST);
//}
///////////////////////////////////
// DRAW CONTENT
// setup the stencil test function like this:
// for each pixel of this node and its children
// if all layers less than or equals to the current are set to 1 in the stencil buffer
// draw the pixel and keep the current layer in the stencil buffer
// else
// do not draw the pixel but keep the current layer in the stencil buffer
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
// RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_EQUAL, _mask_layer_le, _mask_layer_le);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP);
// draw (according to the stencil test function) this node and its children
}
void ClippingNode::onAfterVisit()
{
///////////////////////////////////
// CLEANUP
// manually restore the stencil state
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
// RenderState::StateBlock::_defaultState->setStencilFunction((RenderState::StencilFunction)_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
// RenderState::StateBlock::_defaultState->setStencilOperation((RenderState::StencilOperation)_currentStencilFail,
// (RenderState::StencilOperation)_currentStencilPassDepthFail,
// (RenderState::StencilOperation)_currentStencilPassDepthPass);
glStencilMask(_currentStencilWriteMask);
if (!_currentStencilEnabled)
{
glDisable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(false);
}
// we are done using this layer, decrement
s_layer--;
}
NS_CC_END

View File

@ -34,6 +34,8 @@
#include "renderer/CCCustomCommand.h"
NS_CC_BEGIN
class StencilStateManager;
/**
* @addtogroup _2d
* @{
@ -153,34 +155,9 @@ CC_CONSTRUCTOR_ACCESS:
virtual bool init(Node *stencil);
protected:
/**draw fullscreen quad to clear stencil bits
*/
void drawFullScreenQuadClearStencil();
Node* _stencil;
GLfloat _alphaThreshold;
bool _inverted;
//renderData and callback
void onBeforeVisit();
void onAfterDrawStencil();
void onAfterVisit();
GLboolean _currentStencilEnabled;
GLuint _currentStencilWriteMask;
GLenum _currentStencilFunc;
GLint _currentStencilRef;
GLuint _currentStencilValueMask;
GLenum _currentStencilFail;
GLenum _currentStencilPassDepthFail;
GLenum _currentStencilPassDepthPass;
GLboolean _currentDepthWriteMask;
GLboolean _currentAlphaTestEnabled;
GLenum _currentAlphaTestFunc;
GLclampf _currentAlphaTestRef;
GLint _mask_layer_le;
StencilStateManager* _stencilStateManager;
GroupCommand _groupCommand;
CustomCommand _beforeVisitCmd;

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -433,6 +433,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
<ClCompile Include="..\base\ccFPSImages.c" />
<ClCompile Include="..\base\CCIMEDispatcher.cpp" />
<ClCompile Include="..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="..\base\CCStencilStateManager.cpp" />
<ClCompile Include="..\base\CCNS.cpp" />
<ClCompile Include="..\base\CCProfiling.cpp" />
<ClCompile Include="..\base\CCProperties.cpp" />
@ -1015,6 +1016,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
<ClInclude Include="..\base\ccMacros.h" />
<ClInclude Include="..\base\CCMap.h" />
<ClInclude Include="..\base\CCNinePatchImageParser.h" />
<ClInclude Include="..\base\CCStencilStateManager.h" />
<ClInclude Include="..\base\CCNS.h" />
<ClInclude Include="..\base\CCProfiling.h" />
<ClInclude Include="..\base\CCProperties.h" />
@ -1384,4 +1386,4 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.*
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="physics">
@ -1896,6 +1896,9 @@
<ClCompile Include="..\base\CCNinePatchImageParser.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\base\CCStencilStateManager.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="..\renderer\CCFrameBuffer.cpp">
<Filter>renderer</Filter>
@ -3728,6 +3731,9 @@
<ClInclude Include="..\base\CCNinePatchImageParser.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\base\CCStencilStateManager.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\base\CCNinePatchImageParser.h" />
<ClInclude Include="..\renderer\CCFrameBuffer.h">
<Filter>renderer</Filter>
@ -3810,4 +3816,4 @@
<Filter>3d</Filter>
</None>
</ItemGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
@ -286,6 +286,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\ccMacros.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCMap.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCStencilStateManager.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNS.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProfiling.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProperties.h" />
@ -917,6 +918,7 @@
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCIMEDispatcher.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCStencilStateManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNS.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProfiling.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCProperties.cpp" />
@ -1286,4 +1288,4 @@
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)targetver.h" />
@ -1812,6 +1812,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCStencilStateManager.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DConstraint.h">
<Filter>physics3d</Filter>
</ClInclude>
@ -3525,6 +3528,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCNinePatchImageParser.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\base\CCStencilStateManager.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CCPhysics3DDebugDrawer.cpp">
<Filter>physics3d</Filter>
</ClCompile>
@ -3979,4 +3985,4 @@
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)..\..\..\..\physics3d\CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
@ -415,6 +415,7 @@
</ClCompile>
<ClCompile Include="..\..\base\CCIMEDispatcher.cpp" />
<ClCompile Include="..\..\base\CCNinePatchImageParser.cpp" />
<ClCompile Include="..\..\base\CCStencilStateManager.cpp" />
<ClCompile Include="..\..\base\CCNS.cpp" />
<ClCompile Include="..\..\base\CCProfiling.cpp" />
<ClCompile Include="..\..\base\CCProperties.cpp" />
@ -1013,6 +1014,7 @@
<ClInclude Include="..\..\base\ccMacros.h" />
<ClInclude Include="..\..\base\CCMap.h" />
<ClInclude Include="..\..\base\CCNinePatchImageParser.h" />
<ClInclude Include="..\..\base\CCStencilStateManager.h" />
<ClInclude Include="..\..\base\CCNS.h" />
<ClInclude Include="..\..\base\CCProfiling.h" />
<ClInclude Include="..\..\base\CCProperties.h" />
@ -1673,4 +1675,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
@ -1767,6 +1767,9 @@
<ClCompile Include="..\..\base\CCNinePatchImageParser.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\base\CCStencilStateManager.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\renderer\CCMaterial.cpp">
<Filter>renderer</Filter>
</ClCompile>
@ -3635,6 +3638,9 @@
<ClInclude Include="..\..\base\CCNinePatchImageParser.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\base\CCStencilStateManager.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\renderer\CCMaterial.h">
<Filter>renderer</Filter>
</ClInclude>
@ -4017,4 +4023,4 @@
<Filter>3d</Filter>
</None>
</ItemGroup>
</Project>
</Project>

View File

@ -107,6 +107,7 @@ math/Vec2.cpp \
math/Vec3.cpp \
math/Vec4.cpp \
base/CCNinePatchImageParser.cpp \
base/CCStencilStateManager.cpp \
base/CCAsyncTaskPool.cpp \
base/CCAutoreleasePool.cpp \
base/CCConfiguration.cpp \

View File

@ -0,0 +1,309 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCStencilStateManager.hpp"
#include "base/CCDirector.h"
#include "renderer/CCGLProgramCache.h"
#include "renderer/ccGLStateCache.h"
#include "renderer/CCRenderer.h"
#include "renderer/CCRenderState.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
#define CC_CLIPPING_NODE_OPENGLES 0
#else
#define CC_CLIPPING_NODE_OPENGLES 1
#endif
NS_CC_BEGIN
GLint StencilStateManager::s_layer = -1;
static GLint g_sStencilBits = -1;
StencilStateManager::StencilStateManager()
: _alphaThreshold(1.0f)
, _inverted(false)
, _currentStencilEnabled(GL_FALSE)
, _currentStencilWriteMask(~0)
, _currentStencilFunc(GL_ALWAYS)
, _currentStencilRef(0)
, _currentStencilValueMask(~0)
, _currentStencilFail(GL_KEEP)
, _currentStencilPassDepthFail(GL_KEEP)
, _currentStencilPassDepthPass(GL_KEEP)
, _currentDepthWriteMask(GL_TRUE)
, _currentAlphaTestEnabled(GL_FALSE)
, _currentAlphaTestFunc(GL_ALWAYS)
, _currentAlphaTestRef(1)
{
// get (only once) the number of bits of the stencil buffer
static bool once = true;
if (once)
{
glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits);
if (g_sStencilBits <= 0)
{
CCLOG("Stencil buffer is not enabled.");
}
once = false;
}
}
void StencilStateManager::drawFullScreenQuadClearStencil()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when setting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Vec2 vertices[] = {
Vec2(-1.0f, -1.0f),
Vec2(1.0f, -1.0f),
Vec2(1.0f, 1.0f),
Vec2(-1.0f, 1.0f)
};
auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_U_COLOR);
int colorLocation = glProgram->getUniformLocation("u_color");
CHECK_GL_ERROR_DEBUG();
Color4F color(1, 1, 1, 1);
glProgram->use();
glProgram->setUniformsForBuiltins();
glProgram->setUniformLocationWith4fv(colorLocation, (GLfloat*) &color.r, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 4);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void StencilStateManager::setAlphaThreshold(GLfloat alphaThreshold)
{
_alphaThreshold = alphaThreshold;
}
GLfloat StencilStateManager::getAlphaThreshold()const
{
return _alphaThreshold;
}
void StencilStateManager::setInverted(bool inverted)
{
_inverted = inverted;
}
bool StencilStateManager::isInverted()const
{
return _inverted;
}
void StencilStateManager::onBeforeVisit()
{
///////////////////////////////////
// INIT
// increment the current layer
s_layer++;
// mask of the current layer (ie: for layer 3: 00000100)
GLint mask_layer = 0x1 << s_layer;
// mask of all layers less than the current (ie: for layer 3: 00000011)
GLint mask_layer_l = mask_layer - 1;
// mask of all layers less than or equal to the current (ie: for layer 3: 00000111)
_mask_layer_le = mask_layer | mask_layer_l;
// manually save the stencil state
_currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&_currentStencilWriteMask);
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&_currentStencilFunc);
glGetIntegerv(GL_STENCIL_REF, &_currentStencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&_currentStencilValueMask);
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&_currentStencilFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&_currentStencilPassDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
// enable stencil use
glEnable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(true);
// check for OpenGL error while enabling stencil test
CHECK_GL_ERROR_DEBUG();
// 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
glStencilMask(mask_layer);
// RenderState::StateBlock::_defaultState->setStencilWrite(mask_layer);
// manually save the depth test state
glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
// disable depth test while drawing the stencil
//glDisable(GL_DEPTH_TEST);
// 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
glDepthMask(GL_FALSE);
RenderState::StateBlock::_defaultState->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
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(!_inverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP);
// draw a fullscreen solid rectangle to clear the stencil buffer
//ccDrawSolidRect(Vec2::ZERO, ccpFromSize([[Director sharedDirector] winSize]), Color4F(1, 1, 1, 1));
drawFullScreenQuadClearStencil();
///////////////////////////////////
// DRAW CLIPPING STENCIL
// 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
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
// RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_NEVER, mask_layer, mask_layer);
glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(
// !_inverted ? RenderState::STENCIL_OP_REPLACE : RenderState::STENCIL_OP_ZERO,
// RenderState::STENCIL_OP_KEEP,
// RenderState::STENCIL_OP_KEEP);
// enable alpha test only if the alpha threshold < 1,
// indeed if alpha threshold == 1, every pixel will be drawn anyways
if (_alphaThreshold < 1) {
#if !CC_CLIPPING_NODE_OPENGLES
// manually save the alpha test state
_currentAlphaTestEnabled = glIsEnabled(GL_ALPHA_TEST);
glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint *)&_currentAlphaTestFunc);
glGetFloatv(GL_ALPHA_TEST_REF, &_currentAlphaTestRef);
// enable alpha testing
glEnable(GL_ALPHA_TEST);
// check for OpenGL error while enabling alpha test
CHECK_GL_ERROR_DEBUG();
// pixel will be drawn only if greater than an alpha threshold
glAlphaFunc(GL_GREATER, _alphaThreshold);
#endif
}
//Draw _stencil
}
void StencilStateManager::onAfterDrawStencil()
{
// restore alpha test state
if (_alphaThreshold < 1)
{
#if CC_CLIPPING_NODE_OPENGLES
// FIXME: we need to find a way to restore the shaders of the stencil node and its children
#else
// manually restore the alpha test state
glAlphaFunc(_currentAlphaTestFunc, _currentAlphaTestRef);
if (!_currentAlphaTestEnabled)
{
glDisable(GL_ALPHA_TEST);
}
#endif
}
// restore the depth test state
glDepthMask(_currentDepthWriteMask);
RenderState::StateBlock::_defaultState->setDepthWrite(_currentDepthWriteMask != 0);
//if (currentDepthTestEnabled) {
// glEnable(GL_DEPTH_TEST);
//}
///////////////////////////////////
// DRAW CONTENT
// setup the stencil test function like this:
// for each pixel of this node and its children
// if all layers less than or equals to the current are set to 1 in the stencil buffer
// draw the pixel and keep the current layer in the stencil buffer
// else
// do not draw the pixel but keep the current layer in the stencil buffer
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
// RenderState::StateBlock::_defaultState->setStencilFunction(RenderState::STENCIL_EQUAL, _mask_layer_le, _mask_layer_le);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP, RenderState::STENCIL_OP_KEEP);
// draw (according to the stencil test function) this node and its children
}
void StencilStateManager::onAfterVisit()
{
///////////////////////////////////
// CLEANUP
// manually restore the stencil state
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
// RenderState::StateBlock::_defaultState->setStencilFunction((RenderState::StencilFunction)_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
// RenderState::StateBlock::_defaultState->setStencilOperation((RenderState::StencilOperation)_currentStencilFail,
// (RenderState::StencilOperation)_currentStencilPassDepthFail,
// (RenderState::StencilOperation)_currentStencilPassDepthPass);
glStencilMask(_currentStencilWriteMask);
if (!_currentStencilEnabled)
{
glDisable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(false);
}
// we are done using this layer, decrement
s_layer--;
}
NS_CC_END

View File

@ -0,0 +1,79 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2015 Chukong Technologies Inc.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef StencilStateManager_hpp
#define StencilStateManager_hpp
#include "base/ccConfig.h"
#include "platform/CCPlatformMacros.h"
#include "platform/CCGL.h"
/**
* @addtogroup base
* @{
*/
NS_CC_BEGIN
class CC_DLL StencilStateManager
{
public:
StencilStateManager();
void onBeforeVisit();
void onAfterDrawStencil();
void onAfterVisit();
void setAlphaThreshold(GLfloat alphaThreshold);
void setInverted(bool inverted);
bool isInverted()const;
GLfloat getAlphaThreshold()const;
private:
CC_DISALLOW_COPY_AND_ASSIGN(StencilStateManager);
static GLint s_layer;
/**draw fullscreen quad to clear stencil bits
*/
void drawFullScreenQuadClearStencil();
GLfloat _alphaThreshold;
bool _inverted;
GLboolean _currentStencilEnabled;
GLuint _currentStencilWriteMask;
GLenum _currentStencilFunc;
GLint _currentStencilRef;
GLuint _currentStencilValueMask;
GLenum _currentStencilFail;
GLenum _currentStencilPassDepthFail;
GLenum _currentStencilPassDepthPass;
GLboolean _currentDepthWriteMask;
GLboolean _currentAlphaTestEnabled;
GLenum _currentAlphaTestFunc;
GLclampf _currentAlphaTestRef;
GLint _mask_layer_le;
};
NS_CC_END
// end of base group
/** @} */
#endif /* StencilStateManager_hpp */

View File

@ -45,6 +45,7 @@ set(COCOS_BASE_SRC
base/CCUserDefault.cpp
base/CCValue.cpp
base/ObjectFactory.cpp
base/CCStencilStateManager.cpp
base/TGAlib.cpp
base/ZipUtils.cpp
base/allocator/CCAllocatorDiagnostics.cpp

View File

@ -37,6 +37,7 @@ THE SOFTWARE.
#include "2d/CCLayer.h"
#include "2d/CCSprite.h"
#include "base/CCEventFocus.h"
#include "base/CCStencilStateManager.hpp"
#include "2d/CocosStudioExtension.h"
@ -46,9 +47,6 @@ namespace ui {
static const int BACKGROUNDIMAGE_Z = (-1);
static const int BCAKGROUNDCOLORRENDERER_Z = (-2);
static GLint g_sStencilBits = -1;
static GLint s_layer = -1;
IMPLEMENT_CLASS_GUI_INFO(Layout)
@ -76,18 +74,7 @@ _clippingStencil(nullptr),
_clippingRect(Rect::ZERO),
_clippingParent(nullptr),
_clippingRectDirty(true),
_currentStencilEnabled(GL_FALSE),
_currentStencilWriteMask(~0),
_currentStencilFunc(GL_ALWAYS),
_currentStencilRef(0),
_currentStencilValueMask(~0),
_currentStencilFail(GL_KEEP),
_currentStencilPassDepthFail(GL_KEEP),
_currentStencilPassDepthPass(GL_KEEP),
_currentDepthWriteMask(GL_TRUE),
_currentAlphaTestEnabled(GL_FALSE),
_currentAlphaTestFunc(GL_ALWAYS),
_currentAlphaTestRef(1),
_stencileStateManager(new StencilStateManager()),
_doLayoutDirty(true),
_isInterceptTouch(false),
_loopFocus(false),
@ -266,13 +253,13 @@ void Layout::stencilClippingVisit(Renderer *renderer, const Mat4& parentTransfor
renderer->pushGroup(_groupCommand.getRenderQueueID());
_beforeVisitCmdStencil.init(_globalZOrder);
_beforeVisitCmdStencil.func = CC_CALLBACK_0(Layout::onBeforeVisitStencil, this);
_beforeVisitCmdStencil.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencileStateManager);
renderer->addCommand(&_beforeVisitCmdStencil);
_clippingStencil->visit(renderer, _modelViewTransform, flags);
_afterDrawStencilCmd.init(_globalZOrder);
_afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this);
_afterDrawStencilCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterDrawStencil, _stencileStateManager);
renderer->addCommand(&_afterDrawStencilCmd);
int i = 0; // used by _children
@ -320,7 +307,7 @@ void Layout::stencilClippingVisit(Renderer *renderer, const Mat4& parentTransfor
_afterVisitCmdStencil.init(_globalZOrder);
_afterVisitCmdStencil.func = CC_CALLBACK_0(Layout::onAfterVisitStencil, this);
_afterVisitCmdStencil.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencileStateManager);
renderer->addCommand(&_afterVisitCmdStencil);
renderer->popGroup();
@ -328,136 +315,6 @@ void Layout::stencilClippingVisit(Renderer *renderer, const Mat4& parentTransfor
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void Layout::onBeforeVisitStencil()
{
s_layer++;
GLint mask_layer = 0x1 << s_layer;
GLint mask_layer_l = mask_layer - 1;
_mask_layer_le = mask_layer | mask_layer_l;
_currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&_currentStencilWriteMask);
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&_currentStencilFunc);
glGetIntegerv(GL_STENCIL_REF, &_currentStencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&_currentStencilValueMask);
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&_currentStencilFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&_currentStencilPassDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
glEnable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(true);
CHECK_GL_ERROR_DEBUG();
glStencilMask(mask_layer);
// RenderState::StateBlock::_defaultState->setStencilWrite(mask_layer);
glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
glDepthMask(GL_FALSE);
RenderState::StateBlock::_defaultState->setDepthWrite(false);
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);
this->drawFullScreenQuadClearStencil();
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
// RenderState::StateBlock::_defaultState->setStencilFunction(
// RenderState::STENCIL_NEVER,
// mask_layer,
// mask_layer);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(
// RenderState::STENCIL_OP_REPLACE,
// RenderState::STENCIL_OP_KEEP,
// RenderState::STENCIL_OP_KEEP);
}
void Layout::drawFullScreenQuadClearStencil()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when setting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Vec2 vertices[] =
{
Vec2(-1, -1),
Vec2(1, -1),
Vec2(1, 1),
Vec2(-1, 1)
};
auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_U_COLOR);
int colorLocation = glProgram->getUniformLocation("u_color");
CHECK_GL_ERROR_DEBUG();
Color4F color(1, 1, 1, 1);
glProgram->use();
glProgram->setUniformsForBuiltins();
glProgram->setUniformLocationWith4fv(colorLocation, (GLfloat*) &color.r, 1);
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 4);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void Layout::onAfterDrawStencil()
{
glDepthMask(_currentDepthWriteMask);
RenderState::StateBlock::_defaultState->setDepthWrite(_currentDepthWriteMask != 0);
glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
// RenderState::StateBlock::_defaultState->setStencilFunction(
// RenderState::STENCIL_EQUAL,
// _mask_layer_le,
// _mask_layer_le);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// RenderState::StateBlock::_defaultState->setStencilOperation(
// RenderState::STENCIL_OP_KEEP,
// RenderState::STENCIL_OP_KEEP,
// RenderState::STENCIL_OP_KEEP);
}
void Layout::onAfterVisitStencil()
{
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
// RenderState::StateBlock::_defaultState->setStencilFunction(
// (RenderState::StencilFunction)_currentStencilFunc,
// _currentStencilRef,
// _currentStencilValueMask);
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
// RenderState::StateBlock::_defaultState->setStencilOperation(
// (RenderState::StencilOperation)_currentStencilFail,
// (RenderState::StencilOperation)_currentStencilPassDepthFail,
// (RenderState::StencilOperation)_currentStencilPassDepthPass);
glStencilMask(_currentStencilWriteMask);
if (!_currentStencilEnabled)
{
glDisable(GL_STENCIL_TEST);
// RenderState::StateBlock::_defaultState->setStencilTest(false);
}
s_layer--;
}
void Layout::onBeforeVisitScissor()
{
auto glview = Director::getInstance()->getOpenGLView();
@ -530,16 +387,6 @@ void Layout::setClippingEnabled(bool able)
case ClippingType::STENCIL:
if (able)
{
static bool once = true;
if (once)
{
glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits);
if (g_sStencilBits <= 0)
{
CCLOG("Stencil buffer is not enabled.");
}
once = false;
}
_clippingStencil = DrawNode::create();
if (_running)
{

View File

@ -39,9 +39,9 @@ NS_CC_BEGIN
class DrawNode;
class LayerColor;
class LayerGradient;
class StencilStateManager;
struct CC_DLL ResouceData;
namespace ui {
class LayoutManager;
@ -489,12 +489,6 @@ protected:
virtual const Vector<Node*>& getLayoutElements()const override;
//clipping
void onBeforeVisitStencil();
void onAfterDrawStencil();
void onAfterVisitStencil();
/**draw fullscreen quad to clear stencil bits
*/
void drawFullScreenQuadClearStencil();
void onBeforeVisitScissor();
void onAfterVisitScissor();
@ -638,23 +632,8 @@ protected:
bool _clippingRectDirty;
//clipping
StencilStateManager *_stencileStateManager;
GLboolean _currentStencilEnabled;
GLuint _currentStencilWriteMask;
GLenum _currentStencilFunc;
GLint _currentStencilRef;
GLuint _currentStencilValueMask;
GLenum _currentStencilFail;
GLenum _currentStencilPassDepthFail;
GLenum _currentStencilPassDepthPass;
GLboolean _currentDepthWriteMask;
GLboolean _currentAlphaTestEnabled;
GLenum _currentAlphaTestFunc;
GLclampf _currentAlphaTestRef;
GLint _mask_layer_le;
GroupCommand _groupCommand;
CustomCommand _beforeVisitCmdStencil;
CustomCommand _afterDrawStencilCmd;

View File

@ -123,6 +123,16 @@ bool UIListViewTest_Vertical::init()
custom_item->addChild(custom_button);
listView->addChild(custom_item);
auto clippingNode = ClippingNode::create();
auto sprite = Sprite::create("cocosui/clippingHead.jpg");
clippingNode->addChild(sprite);
auto stencil = Sprite::create("cocosui/clippingStencil.jpg");
clippingNode->setStencil(stencil);
auto custom_item_contentSize = custom_item->getContentSize();
clippingNode->setPosition(custom_item_contentSize.width/2, custom_item_contentSize.height/2);
clippingNode->setScale(0.5);
custom_item->addChild(clippingNode);
}
// insert custom item
Vector<Widget*>& items = listView->getItems();

@ -1 +1 @@
Subproject commit 636129882b612b5fe6d1d21be1eec136a2b1340b
Subproject commit e82bd71212e53e016bf5f262f8e4bc1c50b54203

@ -1 +1 @@
Subproject commit a0fe326ea3d685d342ba2a61c0be6f9dee83f800
Subproject commit 2318a1593d2d490a3860179acaf81a1bf867a36b