taoru's memo

Objective-c,cocos2d,など開発についてのメモ(andoroidも少しだけ)

cocos2dv2.1で追加されたCCClippingNodeを試す

この記事は、cocos2dv2.1で追加されたCCDrawNodeを試す - taoru's memo の続きです。
今回はCCClippingNodeを試す。これを使うといわゆるmask効果を得られる。

が、適当に試しててもなかなか思い通りにできなかったので、練習する。

CCClippingNode.h についてるコメント

/** CCClippingNode is a subclass of CCNode.
It draws its content (childs) clipped using a stencil.
The stencil is an other CCNode that will not be drawn.
The clipping is done using the alpha part of the stencil (adjusted with an alphaThreshold).
*/

stencilによって、clippingNodeにaddChildされたCCNodeをクリッピングする。
そのstencilは(clippingNodeとは別の?)CCNodeで、描画されることがない。
stencilの透過部分がクリッピングに使われる

setできるparameter

/** The CCNode to use as a stencil to do the clipping.
 The stencil node will be retained.
 This default to nil.
 */
@property (nonatomic, retain) CCNode *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).
 */
@property (nonatomic) GLfloat alphaThreshold;

/** 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.
 */
@property (nonatomic) BOOL inverted;

以下は私の解釈

  • stencil
    • stencilTestに使用されるCCNode, このNodeによってマスクされる
  • alphaThreshold
    • 直訳でalpha値のしきい値
    • stencilのうちalphaThresholdより大きいalpha値を持つpixelのみコンテンツが描画される。
  • inverted
    • これがYESだとstencilTestの結果が逆転して、stencilが描画されない領域だけが描画されるようになる。

英語が弱すぎてかなりあやふやですが、そこはTry&Errorでカバーしましょう…


が、いっこうにうまくいかない

まずAppDelegate.m のCCGLViewを定義している箇所を書き換えて、stencil bufferを有効にする(たぶん)

	// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
	CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
								   pixelFormat:kEAGLColorFormatRGB565
								   depthFormat:GL_DEPTH24_STENCIL8_OES //GL_DEPTH_COMPONENT24_OES
							preserveBackbuffer:NO
									sharegroup:nil
								 multiSampling:NO
							   numberOfSamples:0];

サンプルを元に、ClippingNodeを試す(NGコード)

- (id)init
{
    if (self = [super init]) {
        CGPoint square[]   = { {-100,-100}, {100,-100}, {100,100}, {-100,100} };
        CGPoint triangle[] = { {-50,-50}, {50,-50}, {0,50}};
        ccColor4F green = ccc4FFromccc3B(ccGREEN);
        ccColor4F red  = ccc4FFromccc3B(ccRED);
        
        // contents部分 これを表示させたい
        CCDrawNode *content = [CCDrawNode node];
        [content drawPolyWithVerts:square count:4 fillColor:green borderWidth:0 borderColor:green];
        content.position = ccp(50, 50);
        
        // stencil これでマスクする
        CCDrawNode *stencil = [CCDrawNode node];
        [stencil drawPolyWithVerts:triangle count:3 fillColor:red borderWidth:0 borderColor:red];
        stencil.position  = ccp(50, 50);
        [stencil runAction:[CCRepeatForever actionWithAction:[CCRotateBy actionWithDuration:1 angle:90]]];

        CCClippingNode *clippingNode = [CCClippingNode clippingNode];
        clippingNode.anchorPoint          = ccp(0.5f, 0.5f);
        clippingNode.alphaThreshold    = 0.05f;
        clippingNode.stencil = stencil;

        // clippingしたいnodeを、clippingNodeにaddChildする
        [clippingNode addChild:content];
        
        clippingNode.position = ccp(self.contentSize.width/2 -50, self.contentSize.height/2 - 50);
        [self addChild:clippingNode];
        
    }
    return self;
}

これを実行すると…

サンプルとほぼ同じなのに、できない。何がいけないんだろう。

追記1

alphaThresholdの指定を外したらできた!(defaultでは1になってる)
alphaThresholdについての理解ができていない。まだまだマスターには遠いな。

上記からalphaThresholdを外して、contentにCCSpriteを使ってみた。

- (id)init
{
    if (self = [super init]) {
        
        CGPoint triangle[] = { {-100,-100}, {100,-100}, {0,100}};
        ccColor4F red   = ccc4FFromccc3B(ccRED);
        
        // contents部分 これを表示させたい
        CCSprite *content = [CCSprite spriteWithFile:@"Default@2x.png"];
        content.position = ccp(50, 50);
        
        // stencil これでマスクする
        CCDrawNode *stencil = [CCDrawNode node];
        [stencil drawPolyWithVerts:triangle count:3 fillColor:red borderWidth:0 borderColor:red];
        stencil.position    = ccp(50, 50);
        [stencil runAction:[CCRepeatForever actionWithAction:[CCRotateBy actionWithDuration:1 angle:90]]];

        CCClippingNode *clippingNode = [CCClippingNode clippingNode];
        clippingNode.anchorPoint     = ccp(0.5f, 0.5f);
        clippingNode.stencil         = stencil;

        [clippingNode addChild:content];
        
        clippingNode.position = ccp(self.contentSize.width/2 -50, self.contentSize.height/2 - 50);
        [self addChild:clippingNode];
    }
    return self;
}

stencilを回転させている。

clippingNode.inverted = YES; にすると描画範囲が逆転

こいつは面白い。

次にstencil部分に CCSpriteを使ってみた。

ペイントソフトで作ったお粗末な画像

- (id)init
{
    if (self = [super init]) {
        
//        CGPoint triangle[] = { {-100,-100}, {100,-100}, {0,100}};
//        ccColor4F red   = ccc4FFromccc3B(ccRED);
        
        // contents部分 これを表示させたい
        CCSprite *content = [CCSprite spriteWithFile:@"Default@2x.png"];
        content.position = ccp(50, 50);
        
        // stencil これでマスクする
//        CCDrawNode *stencil = [CCDrawNode node];
//        [stencil drawPolyWithVerts:triangle count:3 fillColor:red borderWidth:0 borderColor:red];
        CCSprite *stencil = [CCSprite spriteWithFile:@"star.png"];
        stencil.position    = ccp(50, 50);
        stencil.scale       = 1.5f;
        [stencil runAction:[CCRepeatForever actionWithAction:[CCRotateBy actionWithDuration:1 angle:90]]];

        CCClippingNode *clippingNode = [CCClippingNode clippingNode];
        clippingNode.anchorPoint     = ccp(0.5f, 0.5f);
        clippingNode.stencil         = stencil;
        clippingNode.alphaThreshold  = 0.01;
        
        [clippingNode addChild:content];
        
        clippingNode.position = ccp(self.contentSize.width/2 -50, self.contentSize.height/2 - 50);
        [self addChild:clippingNode];
    }
    return self;
}

結果

CCSpriteをstencilに用いるときは、alphaThresholdを設定する必要があった。
default(1.0f)だと何も表示されなかったので、0より大きい0.01をセットした。


    • 2013/03/06

childやstencilにCCNodeを使い、更にactionがつく場合の制御が意外と難しい。
CCNodeのcontentSizeが関係しているかも?

QLOOKアクセス解析