本文主要是介绍CCClippingNode(Clip修剪 可以实现新手引导遮罩、滚动字幕。。渲染child时仅渲染模板透明度值大于透明度阀值的像素点.默认透明度阀值 =1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://blog.csdn.net/univcore/article/details/42149725 |
Cocos2d-x开发--使用CCRenderTexture将矩形图片裁剪成圆形显示
CCNode* m_pStencil;//模板 简单的模板可以用CCDrawNode 、 CCLayerColor来做 。 复杂的可以通过ccsprite 使用图片做
cocos2d-x利用CCClippingNode实现滚动字幕 - 白白手游专栏(...
要实现文字在一定区域里滚动,首先用CCClippingNode做出一个剪裁区域,在这个区域内文字可以显示,出了这个区域之后文字就看不到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | bool TestLayer::init() { CCSize size = CCDirector::sharedDirector()->getVisibleSize(); //创建要显示的文字 text = CCLabelTTF::create( "text\nbaibai\n白白\nbaibai\nhaha\nhaha\nahha\n" , "" , 30 ); text->setPosition(ccp( 100 , - 120 )); //绘制裁剪区域 CCDrawNode* shap = CCDrawNode::create(); CCPoint point[ 4 ] = {ccp( 0 , 0 ), ccp( 200 , 0 ), ccp( 200 , 200 ), ccp( 0 , 200 )}; shap->drawPolygon(point, 4 , ccc4f( 355 , 255 , 255 , 255 ), 2 , ccc4f( 255 , 255 , 255 , 255 )); CCClippingNode* cliper = CCClippingNode::create(); cliper->setStencil(shap); cliper->setAnchorPoint(ccp(. 5 , . 5 )); cliper->setPosition(ccp( 100 , 20 )); addChild(cliper); //把要滚动的文字加入到裁剪区域 cliper->addChild(text); //文字滚动,超出范围后从新开始 schedule(schedule_selector(CTestLayer::rollText)); return true ; } void TestLayer::rollText( float ) { text->getPositionY()> 300 ? text->setPositionY(- 150 ) : text->setPositionY(text->getPositionY()+ 2 ); } |
CCClippingNode遮罩解析 - shangguanyingqi的专栏 - 博客频道 - ...
#ifndef __MISCNODE_CCCLIPPING_NODE_H__
#define __MISCNODE_CCCLIPPING_NODE_H__
#include "base_nodes/CCNode.h"
#include "CCGL.h"
NS_CC_BEGIN
/** CCClippingNode is a subclass of CCNode.
It draws its content (childs) clipped using a stencil. //绘制child时会先通过模板裁剪
The stencil is an other CCNode that will not be drawn. //模板也是一个ccnode 但不会被渲染
The clipping is done using the alpha part of the stencil (adjusted(调整) with an alphaThreshold).// 模板只是提供他的alpha 以实现裁剪的效果
*/
class CC_DLL CCClippingNode : public CCNode
{
protected:
// CCClippingNode 在渲染child时 仅渲染模板透明度值 大于 透明度阀值的 像素点 默认透明度阀值 =1
CCNode* m_pStencil;//模板 简单的模板可以用CCDrawNode 、 CCLayerColor来做 。 复杂的可以通过ccsprite 使用图片做
GLfloat m_fAlphaThreshold; //Alpha 透明度 Threshold 阀值工具
bool m_bInverted; //倒转的 反向的
private:
CCClippingNode(); // 私有化构造函数 子类就不能new出此类了 这个类是不准备被派生了
public:
static CCClippingNode*create(); //无模板创建
static CCClippingNode*create(CCNode *pStencil);//通过模板创建
CCNode*getStencil() const; //set get 模板
voidsetStencil(CCNode *pStencil);
GLfloatgetAlphaThreshold() const; //set get AlphaThreshold
voidsetAlphaThreshold(GLfloat fAlphaThreshold);
/** Inverted. If this is set to YES,
the stencil is inverted, so the content is drawn where the stencil is NOT drawn.
This default to NO.
*/
bool isInverted() const;
voidsetInverted(bool bInverted);
virtual ~CCClippingNode();
virtual bool init();
virtual boolinit(CCNode *pStencil);
{
CC_SAFE_RELEASE(m_pStencil);
m_pStencil = pStencil;
CC_SAFE_RETAIN(m_pStencil);
m_fAlphaThreshold = 1;
m_bInverted = 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;
}
virtual void onEnter();
virtual void onEnterTransitionDidFinish();
virtual void onExitTransitionDidStart();
virtual void onExit();
virtual void visit();
};
void CCClippingNode::visit()
{
// if stencil buffer disabled
if (g_sStencilBits < 1)
{
// draw everything, as if there where no stencil
CCNode::visit();
return;
}
// return fast (draw nothing, or draw everything if in inverted mode) if:
// - nil stencil node
// - or stencil node invisible:
if (!m_pStencil || !m_pStencil->isVisible())
{
if (m_bInverted)
{
// draw everything
CCNode::visit();
}
return;
}
// store the current stencil layer (position in the stencil buffer),
// this will allow nesting up to n CCClippingNode,
// where n is the number of bits of the stencil buffer.
static GLint layer = -1;
// all the _stencilBits are in use?
if (layer + 1 == g_sStencilBits)
{
// warn once
static bool once = true;
if (once)
{
char warning[200] = {0};
snprintf(warning, sizeof(warning), "Nesting more than %d stencils is not supported. Everything will be drawn without stencil for this node and its childs.", g_sStencilBits);
CCLOG("%s", warning);
once = false;
}
// draw everything, as if there where no stencil
CCNode::visit();
return;
}
///
// INIT
// increment the current layer
layer++;
// mask of the current layer (ie: for layer 3: 00000100)
GLint mask_layer = 0x1 << 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)
GLint mask_layer_le = mask_layer | mask_layer_l;
// manually save the stencil state
GLboolean currentStencilEnabled = GL_FALSE;
GLuint currentStencilWriteMask = ~0;
GLenum currentStencilFunc = GL_ALWAYS;
GLint currentStencilRef = 0;
GLuint currentStencilValueMask = ~0;
GLenum currentStencilFail = GL_KEEP;
GLenum currentStencilPassDepthFail = GL_KEEP;
GLenum currentStencilPassDepthPass = GL_KEEP;
currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)¤tStencilWriteMask);
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)¤tStencilFunc);
glGetIntegerv(GL_STENCIL_REF, ¤tStencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)¤tStencilValueMask);
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)¤tStencilFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)¤tStencilPassDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)¤tStencilPassDepthPass);
// enable stencil use
glEnable(GL_STENCIL_TEST);
// 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);
// manually save the depth test state
//GLboolean currentDepthTestEnabled = GL_TRUE;
GLboolean currentDepthWriteMask = GL_TRUE;
//currentDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
glGetBooleanv(GL_DEPTH_WRITEMASK, ¤tDepthWriteMask);
// 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);
///
// 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(!m_bInverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP);
// draw a fullscreen solid rectangle to clear the stencil buffer
//ccDrawSolidRect(CCPointZero, ccpFromSize([[CCDirector sharedDirector] winSize]), ccc4f(1, 1, 1, 1));
ccDrawSolidRect(CCPointZero, ccpFromSize(CCDirector::sharedDirector()->getWinSize()), ccc4f(1, 1, 1, 1));
///
// 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);
glStencilOp(!m_bInverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP);
// 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 (m_fAlphaThreshold < 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, m_fAlphaThreshold);
#else
// since glAlphaTest do not exists in OES, use a shader that writes
// pixel only if greater than an alpha threshold
CCGLProgram *program = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColorAlphaTest);
GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), kCCUniformAlphaTestValue);
// set our alphaThreshold
program->setUniformLocationWith1f(alphaValueLocation, m_fAlphaThreshold);
// 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(m_pStencil, program);
#endif
}
// draw the stencil node as if it was one of our child
// (according to the stencil test func/op and alpha (or alpha shader) test)
kmGLPushMatrix();
transform();
m_pStencil->visit();
kmGLPopMatrix();
// restore alpha test state
if (m_fAlphaThreshold < 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) {
// glEnable(GL_DEPTH_TEST);
//}
///
// DRAW CONTENT
// setup the stencil test func like this:
// for each pixel of this node and its childs
// 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);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// draw (according to the stencil test func) this node and its childs
CCNode::visit();
///
// CLEANUP
// manually restore the stencil state
glStencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask);
glStencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass);
glStencilMask(currentStencilWriteMask);
if (!currentStencilEnabled)
{
glDisable(GL_STENCIL_TEST);
}
// we are done using this layer, decrement
layer--;
}
这篇关于CCClippingNode(Clip修剪 可以实现新手引导遮罩、滚动字幕。。渲染child时仅渲染模板透明度值大于透明度阀值的像素点.默认透明度阀值 =1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!