在此示例中,如何将值绘制到模板缓冲区?

How do values get drawn to the stencil buffer in this example?

我在理解 OpenGL 中模板缓冲的工作原理时遇到了严重的问题。我按照教程的示例进行操作,代码当然有效,但我真的不知道我在什么时候写入模板缓冲区。对我来说,似乎我正在设置模板测试、掩码和所有内容,但随后我只是调用 glDrawArrays(...) 并在根本不应用模板缓冲区的情况下将三角形写入输出。 我也不明白为什么我使用 glClear(GL_STENCIL_BUFFER_BIT) 清除缓冲区 在我画三角形之前。如果有人能开导我,我将不胜感激。

// Draws the initial cube facing upwards
glDrawArrays(GL_TRIANGLES, 0, 36); 

//enable stencil testing
glEnable(GL_STENCIL_TEST);

// Draws the floor between the upward cube and downward cube 
glStencilFunc(GL_ALWAYS, 1, 0xFF); /*sets the test function, mask and ref value*/
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); /*defines what happens on restults*/
glStencilMask(0xFF); /*Mask that is applied on the bits before they are written to the stencil buffer*/
glDepthMask(GL_FALSE);
glClear(GL_STENCIL_BUFFER_BIT); /*Why do I clear the buffer here?!?*/
glDrawArrays(GL_TRIANGLES, 36, 6);

// Draws the downward cube (reflection)
glStencilFunc(GL_EQUAL, 1, 0xFF);
glDepthMask(GL_TRUE);
glStencilMask(0x00);

model = glm::scale(
glm::translate(model, glm::vec3(0, 0, -1)),
glm::vec3(1, 1, -1)
);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

glUniform3f(uniColor, 0.3f, 0.3f, 0.3f);
glDrawArrays(GL_TRIANGLES, 0, 36);
glUniform3f(uniColor, 1.0f, 1.0f, 1.0f);

glDisable(GL_STENCIL_TEST);

传递给 glStencilOp (GL_REPLACE) 的第三个值告诉 OpenGL 将模板缓冲区设置为先前在 glStencilFunc 中指定的 ref 值深度测试通过。在这种情况下:1.

然后对 glDrawArrays 的调用将模板缓冲区更新为 1 成功绘制的每个地方(即通过两个测试)。

(你首先清除它的原因是为了摆脱你开始时碰巧在那里的任何 1:你不希望它们在你没有绘制三角形的地方充当误报)。

详情见https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glStencilOp.xml

好的,我想我终于明白了。只是为了向可能有与我在这里遇到的相同思维障碍的任何其他人提供答案,这就是我的问题所在。 在我的脑海里,我认为我必须先以某种方式将值写入模板缓冲区,然后再将它们写入显示器。正如@NicolBolas 所说的那样,这是错误的。

命令 glDrawArrays(当 stencilTesting 处于活动状态时)写入显示以及模板缓冲区。对于接下来的所有内容,我们在缓冲区中都有我的示例地板的模板,并且可以使用它来评估是否将绘制像素。通过这种方式,我们可以有效地让第二个立方体只在地板上绘制,而不是在它外面。由于在我们绘制立方体之前将 glStencilMask 设置为全零,我们确保它不会影响模板缓冲区,即使模板测试应用于操作。如果其他人偶然发现了这一点,我希望这会有所帮助。如果这完全是胡说八道,请任何人对我的想法中的错误发表评论。