在iOS上使用模板缓冲区

5
我尝试使用“模板缓冲区”来显示我的纹理渲染的一部分,但是我的渲染显示没有任何遮罩效果。
这是一个OpenGL ES 2.0的2D iOS项目。 以下是我代码中相关部分:
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glEnable( GL_STENCIL_TEST );


// mask rendering
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glStencilFunc( GL_ALWAYS, 1, 1 );
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );

glBindTexture(GL_TEXTURE_2D, _maskTexture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  


// scene rendering
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); 
glStencilFunc( GL_EQUAL, 1, 1 ); 
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );  

glBindTexture(GL_TEXTURE_2D, _viewTexture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  

任何帮助都将不胜感激!
(像法国开发者一样,抱歉我的英语!)
明确一下:“_maskTexture”是一张黑白图片。
解决方案:
我最终通过 rotoglub 和 tim 的指示解决了我的问题。 谢谢你们俩。
1 / 模板缓冲区未正确创建。 应该这样初始化:
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, 
                             GL_DEPTH24_STENCIL8_OES, 
                             backingWidth, 
                             backingHeight);

这是我渲染不受遮罩影响的主要原因。

2/ 为了能够使用纹理作为遮罩,我将黑色替换为 alpha 通道,并在我的渲染中启用混合。

我的最终渲染代码如下:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
    
glClearStencil(0); 
glClearColor (0.0,0.0,0.0,1);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    

// mask rendering
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable(GL_STENCIL_TEST);
glEnable(GL_ALPHA_TEST);
glBlendFunc( GL_ONE, GL_ONE );
glAlphaFunc( GL_NOTEQUAL, 0.0 );
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    
glBindTexture(GL_TEXTURE_2D, _mask);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);  
    
// scene rendering
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    
glDisable(GL_STENCIL_TEST);
glDisable(GL_ALPHA_TEST);
glBindTexture(GL_TEXTURE_2D, _texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  

1
仅仅描述你的问题为“不工作”并不是真正有帮助的。但我猜想你的问题可能已经在这个其他问题中得到了解决:https://dev59.com/9lvUa4cB1Zd3GeqPv64p - rotoglup
感谢您的评论。所谓“不起作用”,是指“_viewTexture”没有显示出“_maskTexture”的任何遮罩效果。 我将来会尽量更具体地说明。关于您提到的帖子,我已经阅读过了,但如果我没记错的话,他通过着色器解决了自己的问题,并放弃了模板缓冲区。 - EricD
1
在阅读您的解决方案帖子时,我认为您仍然存在问题(可能目前被隐藏):您的第二次渲染通道禁用了模板测试,因此您观察到的遮罩效果不能由此测试引起。此外,混合对于模板测试应该没有用处,只有 alpha 测试才有用。我认为您观察到了所需的遮罩效果,但可能是由于其他原因而不是模板化。 - rotoglup
@EricD:这看起来像是一个GLES1.1的解决方案,对吗?如果是的话:那正是我正在寻找的! - Jonas Byström
1个回答

1
简单来说,问题在于您只是将纹理绘制到场景中,而没有对纹理中的内容进行任何测试。模板缓冲区不关心纹理中的颜色,它只检查:
绘制了一个片段吗?(更新模板缓冲区):(不更新模板缓冲区);
您为纹理的每个像素绘制一个片段,因此纹理中的任何遮罩效果都是无用的。
如果您想使用纹理进行遮罩,则需要在模板缓冲区中丢弃任何不希望更新的片段。
这可以通过着色器中的discard关键字或OpenGLES 1.1中的glAlphaTest/glAlphaFunc来完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接