cocos2d-x目前无法利用opengl es2.0的shader来实现mask效果,如果按照老外提供的renderTexture来实现性能就太差了。
遍寻网上后在cocoachina上找到一个深入了解OpenGL-模板测试,经过改造后终于可以在cocos2d-x中使用,与各位同仁分享一下。
先说下模板缓冲(stencil buffer),这在05年还算是一个比较普及的技术。cocos2d-x现在的版本是不支持stencil buffer的,但opengl es是支持的。
可以简单的动手改造一下:
if (depthFormat_) { if( ! depthBuffer_ ) glGenRenderbuffersOES(1, &depthBuffer_); glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthBuffer_); if( multiSampling_ ) glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samplesToUse_, depthFormat_,backingWidth_, backingHeight_); else glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat_, backingWidth_, backingHeight_); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_); // add by frankyang at 2012/5/8 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBuffer_); // bind color buffer glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer_); }
// Add the view controller's view to the window and display. window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; EAGLView *__glView = [EAGLView viewWithFrame: [window bounds] pixelFormat: kEAGLColorFormatRGBA8 //depthFormat: GL_DEPTH_COMPONENT16_OES depthFormat:GL_DEPTH24_STENCIL8_OES preserveBackbuffer: NO sharegroup:nil multiSampling:NO numberOfSamples:0];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)改成
glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)这样就可以正确清除stencil buffer。
glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x1, 0x1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
void MaskBeginLayer::visit() { if (getChildrenCount() != 0) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x1, 0x1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); CCLayer::visit(); glDisable(GL_ALPHA_TEST); glStencilFunc(GL_NOTEQUAL, 0x1, 0x1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); } }
void MaskEndLayer::visit() { glDisable(GL_STENCIL_TEST); CCLayer::visit(); }