1

我正在尝试通过应用模板缓冲区使用 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

我得到的结果只是我的纹理被绘制而没有从模板上应用任何遮罩。关于这个问题我有几个问题:

  1. 是否可以使用带有 GL_POINTS 的模板缓冲区?
  2. 渲染到纹理时是否可以使用模板缓冲区?
  3. 模板纹理是否必须具有任何特殊属性(纯色、内部格式...等)?
  4. 我的代码有任何明显的错误吗?

这是我正在寻找的结果: 在此处输入图像描述

更新:

正如所选答案所指出的,我的问题主要是我没有将模板附加到 FBO 的模板附件上:

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                      GL_RENDERBUFFER, stencilBufferId);

我不知道渲染到纹理时需要它。其次,我没有使用正确的模板测试。

glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

做了工作。

4

1 回答 1

4

按顺序解决您的问题:

  1. 是否可以使用带有 GL_POINTS 的模板缓冲区?

是的。模板测试适用于所有片段,无论渲染的原始类型如何。在不应用模板测试的情况下写入帧缓冲区的唯一情况是使用glClear().

  1. 渲染到纹理时是否可以使用模板缓冲区?

是的。但是,当您使用 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);
  1. 模板纹理是否必须具有任何特殊属性(纯色、内部格式...等)?

OpenGL ES 2.0 没有模板纹理。您必须使用渲染缓冲区作为模板附件,如上面的代码片段所示。GL_STENCIL_INDEX8是唯一支持可用作模板附件的渲染缓冲区格式。ES 3.0 支持深度/模板纹理。

  1. 我的代码有任何明显的错误吗?

也许。看起来有点奇怪的一件事是,您从未真正在显示的代码中应用模板测试。当您启用模板测试时,您只使用GL_ALWAYSGL_NEVER用于模板功能。顾名思义,这些功能要么总是通过模板测试,要么永远不会通过模板测试。所以你不要让片段通过/失败取决于模板值。在第二次抽奖之前,我会期待这样的事情:

glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

这只会渲染当前模板缓冲区值为 1 的片段,这对应于您使用上一次绘制调用渲染的片段。

于 2014-10-24T08:05:47.657 回答