Like you, I'm not very comfortable with OpenGL. Unlike you this tuto helped me, failing to fully understand, to create one component for one of my project. So I'll try to explain it to you as clearly as I can.
The first thing is that you don't have to worry about the mask's shader. It is just a litle "program" which describe the execution pipeline to produce the mask. There is already wrote and it works (cf: Mask.fsh). Just put it into your project.
Then create and init the mask which will be put as a texture, and associate it to the shader:
- (id)initWithFile:(NSString *)file
{
self = [super initWithFile:file];
if (self) {
// Create your rectangle mask
_maskTexture = [[[CCTextureCache sharedTextureCache] addImage:@"CalendarMask.png"] retain];
// Create and init the shader
self.shaderProgram =
[[[GLProgram alloc]
initWithVertexShaderFilename:@"Shaders/PositionTextureColor.vert"
fragmentShaderFilename:@"Mask.frag"] autorelease];
[shaderProgram_ addAttribute:kCCAttributeNamePosition index:kCCAttribPosition];
[shaderProgram_ addAttribute:kCCAttributeNameColor index:kCCAttribColor];
[shaderProgram_ addAttribute:kCCAttributeNameTexCoord index:kCCAttribTexCoords];
[shaderProgram_ link];
[shaderProgram_ updateUniforms];
// Gets the location of the texture and mask uniforms
_textureLocation = glGetUniformLocation( shaderProgram_->program_, "u_texture");
_maskLocation = glGetUniformLocation( shaderProgram_->program_, "u_mask");
}
return self;
}
To finish override the draw method with this:
- (void)draw
{
CC_NODE_DRAW_SETUP();
ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);
ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
[shaderProgram_ setUniformForModelViewProjectionMatrix];
glActiveTexture(GL_TEXTURE0);
glBindTexture( GL_TEXTURE_2D, [texture_ name] );
glUniform1i(textureLocation_, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture( GL_TEXTURE_2D, [maskTexture_ name] );
glUniform1i(maskLocation_, 1);
#define kQuadSize sizeof(quad_.bl)
long offset = (long)&quad_;
// vertex
NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
// texCoods
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glActiveTexture(GL_TEXTURE0);
}
This will just apply your texture as the mask of the sprite. You don't need another step.
you can add sprites as children of this one and they will be masked automatically.
There is only 3 steps to retain:
- Adding the shader (is already made)
- Initialized the shader and keep track of the mask's texture and location
- Override the draw method with the given method
I hope it'll help you