mirror of https://github.com/axmolengine/axmol.git
Fix Clipping Node
This commit is contained in:
parent
e5ebcb2845
commit
c288e5ef9c
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 *)¤tAlphaTestFunc);
|
||||
glGetFloatv(GL_ALPHA_TEST_REF, ¤tAlphaTestRef);
|
||||
// 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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) );
|
||||
|
|
Loading…
Reference in New Issue