简体   繁体   中英

Cocos2d v3 Apply shader on childnodes

Currently I am toying around with shaders in Cocos2d. My goal is to apply a shader to the entire screen (except one node and it's childnodes) to have an overlay menu while the game is blurred.

Now I found this tutorial to work with shaders in cocos2D which resulted in the following code

CCSprite *aSprite = [CCSprite spriteWithImageNamed:@"Default.png"];
aSprite.contentSizeType = CCSizeTypeNormalized;
aSprite.contentSize = CGSizeMake(0.5,0.5);

NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"CSEEmboss" ofType:@"fsh"];
const GLchar * fragmentSource = (GLchar*) [[NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:nil] UTF8String];
aSprite.shaderProgram = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert
                                                  fragmentShaderByteArray:fragmentSource];
[aSprite.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[aSprite.shaderProgram addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
[aSprite.shaderProgram link];
[aSprite.shaderProgram updateUniforms];

[aSprite.shaderProgram use];

[self.scene addChild:aSprite];

Which indeed applies the emboss to the sprite, however when I add children to that sprite, the shader is not applied there, how should I go about that? My scene contains numerous children and adding and removing the shaders with a loop to every children doesn't seem right to mee.

After some research myself, I think the best way to accomplish this is to use a CCRenderTexture and make a screenshot of the rest of your interface. Then use a blur shader on the CCSprite generated by the Render Texture. You could then position your menu interface above the render texture.

Below is a Cocos-2D Obj-C friendly implementation similar to the one at http://saeedoo.com/?p=644 (Cocos2d-x)

All children nodes of a ShaderNode will be rendered using the given shader.

The shading is done by first rendering all of the children nodes into a CCTextureNode , then rendering that texture with the given shader.

ShaderNode.h

#import "CCNode.h"

@interface ShaderNode : CCNode
-(id)initWithShader:(CCShader*)shader;
@end

ShaderNode.m

#import "ShaderNode.h"
#import "cocos2d.h"

@implementation TRShaderNode
{
    CCShader *_shader;
    CCRenderTexture *_renderTexture;
    CCSprite *_sprite;
}

- (id)initWithShader:(CCShader*)shader {
    self = [super init];
    if (self) {
        NSAssert(shader, @"Shader cannot be nil.");
        _shader = shader;
        CGSize size = [[CCDirector sharedDirector] viewSize];
        _renderTexture = [[CCRenderTexture alloc] initWithWidth:size.width height:size.height pixelFormat:CCTexturePixelFormat_RGBA8888];

        _sprite = [[CCSprite alloc] initWithTexture:_renderTexture.texture rect:CGRectMake(0, 0, _renderTexture.texture.contentSize.width, _renderTexture.texture.contentSize.height)];
        _sprite.position = CGPointZero;
        _sprite.anchorPoint = CGPointZero;
        _sprite.shader = _shader;
    }
    return self;
}

-(void)visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform {
    CCRenderer *textureRenderer = [_renderTexture beginWithClear:0 g:0 b:0 a:0];
    for (CCNode *node in self.children){
        [node visit:textureRenderer parentTransform:parentTransform];
    }
    [_renderTexture end];
    [_sprite visit:renderer parentTransform:parentTransform];
}

@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM