我试图通过应用模板缓冲区使用GL_POINTS在OpenGL ES 2.0中绘制纹理。模板缓冲区应来自纹理。我将结果渲染到另一个纹理,然后将纹理呈现给屏幕。这是我渲染纹理的代码:
//Initialize buffers, initialize texture, bind frameBuffer
.....
glClearStencil(0);
glClear (GL_STENCIL_BUFFER_BIT);
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, stencil);
glUseProgram(program[PROGRAM_POINT].id);
glDrawArrays(GL_POINTS, 0, (int)vertexCount);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_NEVER, 0, 1);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(program[PROGRAM_POINT].id);
glDrawArrays(GL_POINTS, 0, (int)vertexCount);
glDisable(GL_STENCIL_TEST);
....
//Render texture to screen
我得到的结果就是我的纹理被绘制而没有从模板上应用任何遮罩。我对这个问题有几个问题:
这是我要找的结果:
更新:
正如所选答案所指出的,我的问题主要是我没有将模板附加到FBO的模板附件上:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencilBufferId);
我不知道渲染到纹理时需要它。其次,我没有使用正确的模板测试。
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
做完了。
答案 0 :(得分:4)
按顺序解决您的问题:
- 是否可以使用带有GL_POINTS的模板缓冲区?
醇>
是。无论渲染的原始类型如何,模板测试都应用于所有片段。在不应用模板测试的情况下写入帧缓冲区的唯一情况是使用glClear()
。
- 渲染到纹理时是否可以使用模板缓冲区?
醇>
是。但是,使用FBO渲染到纹理时,默认帧缓冲区的模板缓冲区将不。您必须创建一个模板渲染缓冲区,并将其附加到FBO的模板附件:
GLuint stencilBufferId = 0;
glGenRenderbuffers(1, &stencilBufferId);
glBindRenderbuffer(GL_RENDERBUFFER, stencilBufferId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencilBufferId);
- 模板纹理是否必须具有任何特殊属性(纯色,内部格式等)?
醇>
OpenGL ES 2.0没有模板纹理。您必须使用renderbuffer作为模板附件,如上面的代码片段所示。 GL_STENCIL_INDEX8
是渲染缓冲区支持的唯一格式,可用作模板附件。 ES 3.0支持深度/模板纹理。
- 我的代码是否有任何明显的错误?
醇>
也许。看起来有点奇怪的一件事是你从未真正在显示的代码中应用模板测试。在启用模板测试时,只能使用GL_ALWAYS
和GL_NEVER
作为模板功能。顾名思义,这些功能要么总是要么永远不会通过模板测试。所以你不要让片段通过/失败,具体取决于模板值。在第二次抽签之前我会期待这样的事情:
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
这只会渲染当前模板缓冲区值为1的片段,这对应于您使用上一次绘制调用渲染的片段。