Fix Clipping Node

This commit is contained in:
Nite Luo 2013-11-18 14:58:41 -08:00
parent e5ebcb2845
commit c288e5ef9c
6 changed files with 80 additions and 31 deletions

View File

@ -4,6 +4,7 @@
#include "CCNewDrawNode.h"
#include "QuadCommand.h"
NS_CC_BEGIN
@ -39,7 +40,9 @@ bool NewDrawNode::init()
void NewDrawNode::draw()
{
updateTransform();
// QuadCommand* quadCommand = new QuadCommand(0, _vertexZ, 0, _shaderProgram, _blendFunc, )
}
NS_CC_END

View File

@ -114,7 +114,7 @@ void NewSprite::draw(void)
{
updateTransform();
//TODO implement z order
QuadCommand* renderCommand = new QuadCommand(0, _vertexZ,_texture->getName(), _shaderProgram, _blendFunc, &_quad, 1);
QuadCommand* renderCommand = new QuadCommand(0, _vertexZ, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1);
Renderer::getInstance()->addCommand(renderCommand);
}

View File

@ -72,7 +72,11 @@ NewClippingNode::NewClippingNode()
currentStencilFail = GL_KEEP;
currentStencilPassDepthFail = GL_KEEP;
currentStencilPassDepthPass = GL_KEEP;
GLboolean currentDepthWriteMask = GL_TRUE;
currentDepthWriteMask = GL_TRUE;
currentAlphaTestEnabled = GL_FALSE;
currentAlphaTestFunc = GL_ALWAYS;
currentAlphaTestRef = 1;
}
void NewClippingNode::visit()
@ -104,11 +108,6 @@ void NewClippingNode::visit()
void NewClippingNode::beforeVisit()
{
// 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 layer = -1;
///////////////////////////////////
// INIT
@ -182,22 +181,60 @@ void NewClippingNode::beforeVisit()
glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
// since glAlphaTest do not exists in OES, use a shader that writes
// pixel only if greater than an alpha threshold
GLProgram *program = ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST);
GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
// set our alphaThreshold
program->use();
program->setUniformLocationWith1f(alphaValueLocation, _alphaThreshold);
// we need to recursively apply this shader to all the nodes in the stencil node
// XXX: we should have a way to apply shader to all nodes without having to do this
setProgram(_stencil, program);
// enable alpha test only if the alpha threshold < 1,
// indeed if alpha threshold == 1, every pixel will be drawn anyways
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WINDOWS || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
// GLboolean currentAlphaTestEnabled = GL_FALSE;
// GLenum currentAlphaTestFunc = GL_ALWAYS;
// GLclampf currentAlphaTestRef = 1;
#endif
if (_alphaThreshold < 1) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WINDOWS || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
// 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);
#else
// since glAlphaTest do not exists in OES, use a shader that writes
// pixel only if greater than an alpha threshold
GLProgram *program = ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST);
GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
// set our alphaThreshold
program->use();
program->setUniformLocationWith1f(alphaValueLocation, _alphaThreshold);
// we need to recursively apply this shader to all the nodes in the stencil node
// XXX: we should have a way to apply shader to all nodes without having to do this
setProgram(_stencil, program);
#endif
}
//Draw _stencil
}
void NewClippingNode::afterDrawStencil()
{
// restore alpha test state
if (_alphaThreshold < 1)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WINDOWS || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
// manually restore the alpha test state
glAlphaFunc(currentAlphaTestFunc, currentAlphaTestRef);
if (!currentAlphaTestEnabled)
{
glDisable(GL_ALPHA_TEST);
}
#else
// XXX: we need to find a way to restore the shaders of the stencil node and its childs
#endif
}
// restore the depth test state
glDepthMask(currentDepthWriteMask);
//if (currentDepthTestEnabled) {

View File

@ -21,7 +21,7 @@ public:
virtual ~NewClippingNode();
void visit();
virtual void visit() override;
protected:
NewClippingNode();
@ -41,6 +41,10 @@ protected:
GLenum currentStencilPassDepthPass;
GLboolean currentDepthWriteMask;
GLboolean currentAlphaTestEnabled;
GLenum currentAlphaTestFunc;
GLclampf currentAlphaTestRef;
GLint mask_layer_le;
};

View File

@ -171,7 +171,7 @@ void Renderer::render()
{
memcpy(_quads + _numQuads, cmd->getQuad(), sizeof(V3F_C4B_T2F_Quad) * cmd->getQuadCount());
_numQuads += cmd->getQuadCount();
_renderStack.top().currentIndex = _lastCommand = i;
_lastCommand = i;
}
else
{
@ -202,11 +202,15 @@ void Renderer::render()
{
flush();
}
_renderStack.top().currentIndex = i;
}
//Draw the batched quads
drawBatchedQuads();
currRenderQueue = _renderGroups[_renderStack.top().renderQueueID];
len = currRenderQueue.size();
//If pop the render stack if we already processed all the commands
if(_renderStack.top().currentIndex + 1 >= len)
{

View File

@ -271,20 +271,21 @@ NewClippingNodeTest::NewClippingNodeTest()
clipper->runAction(RepeatForever::create(RotateBy::create(1, 45)));
this->addChild(clipper);
auto stencil = NewDrawNode::create();
Point rectangle[4];
rectangle[0] = Point(0, 0);
rectangle[1] = Point(clipper->getContentSize().width, 0);
rectangle[2] = Point(clipper->getContentSize().width, clipper->getContentSize().height);
rectangle[3] = Point(0, clipper->getContentSize().height);
Color4F white(1, 1, 1, 1);
stencil->drawPolygon(rectangle, 4, white, 1, white);
clipper->setStencil(stencil);
// auto stencil = NewSprite::create("Images/background2.png");
// auto stencil = NewDrawNode::create();
// Point rectangle[4];
// rectangle[0] = Point(0, 0);
// rectangle[1] = Point(clipper->getContentSize().width, 0);
// rectangle[2] = Point(clipper->getContentSize().width, clipper->getContentSize().height);
// rectangle[3] = Point(0, clipper->getContentSize().height);
//
// Color4F white(1, 1, 1, 1);
// stencil->drawPolygon(rectangle, 4, white, 1, white);
// clipper->setStencil(stencil);
auto stencil = NewSprite::create("Images/grossini.png");
stencil->setPosition(s.width/2, s.height/2);
clipper->setStencil(stencil);
auto content = NewSprite::create("Images/background2.png");
content->setTag( kTagContentNode );
content->setAnchorPoint( Point(0.5, 0.5) );