1、ClippingNode说明
ClippingNode是利用模板遮罩来完成对Node区域裁剪的技术,如何理解ClippingNode的遮罩?看下图的例子吧。
所谓模板,就是一个形状,透过该形状可看到底板上的图层,如果底板上没有任何内容,则直接看到Layer上的内容,而底板上
的东西又不会妨碍Layer上的东西,即模板在底板之外的空间对于Layer来说是透明的。假如有个精灵在模板之外的底板上运动,我们
是看不到它的。除非它进入模板的区域,我们才能看到它。
2、ClippingNode源码
#include "2d/CCNode.h"//用到节点头文件和OPENGL深度缓冲定义头文件
#include "CCGL.h"
#include "renderer/CCGroupCommand.h"//用到GroupCommand和CustomCommand渲染
#include "renderer/CCCustomCommand.h"
NS_CC_BEGIN
/** ClippingNode is a subclass of Node.
It draws its content (childs) clipped using a stencil.
The stencil is an other Node that will not be drawn.
The clipping is done using the alpha part of the stencil (adjusted with an alphaThreshold).
*/
class CC_DLL ClippingNode : public Node
{
public:
/** Creates and initializes a clipping node without a stencil.
*/
static ClippingNode* create();//静态创建对象
/** Creates and initializes a clipping node with an other node as its stencil.
The stencil node will be retained.
*/
static ClippingNode* create(Node *stencil);//用模板创建裁剪节点
/** The Node to use as a stencil to do the clipping.
The stencil node will be retained.
This default to nil.
*/
Node* getStencil() const;//获取节点模板
void setStencil(Node *stencil);//设置节点模板
/** The alpha threshold.
The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold.
Should be a float between 0 and 1.
This default to 1 (so alpha test is disabled).
*///ALPHA测试参考值,用于进行ALPHA测试比较,一般比较算法为小于此值的像素会直接被舍弃,这样就实现了图像的镂空
GLfloat getAlphaThreshold() const;//获取ALPHT的测试参考值
void setAlphaThreshold(GLfloat alphaThreshold);//设置ALPHA的测试参考值
/** Inverted. If this is set to true,
the stencil is inverted, so the content is drawn where the stencil is NOT drawn.
This default to false.
*/
bool isInverted() const;//获取遮罩运算是否取反设置
void setInverted(bool inverted);//设置遮罩运算取反
// Overrides//继承的函数
/**
* @js NA
* @lua NA
*/
virtual void onEnter() override;
/**
* @js NA
* @lua NA
*/
virtual void onEnterTransitionDidFinish() override;
/**
* @js NA
* @lua NA
*/
virtual void onExitTransitionDidStart() override;
/**
* @js NA
* @lua NA
*/
virtual void onExit() override;
virtual void visit(Renderer *renderer, const Mat4 &parentTransform, bool parentTransformUpdated) override;
CC_CONSTRUCTOR_ACCESS:
ClippingNode();
/**
* @js NA
* @lua NA
*/
virtual ~ClippingNode();
/** Initializes a clipping node without a stencil.
*/
virtual bool init();
/** Initializes a clipping node with an other node as its stencil.
The stencil node will be retained, and its parent will be set to this clipping node.
*/
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;
GroupCommand _groupCommand;
CustomCommand _beforeVisitCmd;
CustomCommand _afterDrawStencilCmd;
CustomCommand _afterVisitCmd;
private:
CC_DISALLOW_COPY_AND_ASSIGN(ClippingNode);
};
NS_CC_END
3、使用实例
<pre name="code" class="cpp">class NewClippingNode : public Layer
{
public:
CREATE_FUNC(NewClippingNode);
virtual bool init();
};
bool NewClippingNode::init()
{
auto s =Director::getInstance()->getWinSize();
bool bRet = false;
do{
CC_BREAK_IF(!Layer::init());
auto clipper = ClippingNode::create();
clipper->setTag(kTagClipperNode);
clipper->setContentSize(Size(200,200));//设置剪裁区域大小
clipper->ignoreAnchorPointForPosition(false);
clipper->setAnchorPoint(Vec2(0.5,0.5));//设置锚点
clipper->setPosition(Vec2(s.width/2, s.height/2));
this->addChild(clipper);
clipper->setAlphaThreshold(0.05f);//设置透明度的阈值ALPHA值
//设置剪裁模板
auto stencil = Sprite::create("grossini.png");
stencil->setScale(2);
stencil->setPosition(Vec2(s.width/2, s.height/2));
clipper->setStencil(stencil);//设置剪裁模板
//TODO Fix draw node as clip node
// auto stencil = NewDrawNode::create();
// Vec2 rectangle[4];
// rectangle[0] = Vec2(0, 0);
// rectangle[1] = Vec2(clipper->getContentSize().width, 0);
// rectangle[2] = Vec2(clipper->getContentSize().width, clipper->getContentSize().height);
// rectangle[3] = Vec2(0, clipper->getContentSize().height);
//
// Color4F white(1, 1, 1, 1);
// stencil->drawPolygon(rectangle, 4, white, 1, white);
// clipper->setStencil(stencil);
//设置剪裁节点内容
auto content = Sprite::create("background2.png");
content->setTag(kTagContentNode);
content->ignoreAnchorPointForPosition(false);
content->setAnchorPoint(Vec2(0.5,0.5));
content->setPosition(Vec2(s.width/2,200));
clipper->addChild(content);
bRet =true;
}while(0);
return bRet;
}