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

时间:2019-06-18 16:36:03

标签: c++ opengl glm-math stencil-buffer

我在理解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);

2 个答案:

答案 0 :(得分:2)

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

因此,对glDrawArrays的调用会将模板缓冲区成功绘制的每个位置都更新为1(即通过两个测试)。

(首先清除它的原因是,消除开始时碰巧存在的任何1:您不希望它们在未绘制三角形的情况下充当假阳性)。

有关详细信息,请参见https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glStencilOp.xml

答案 1 :(得分:0)

好的,我想我终于明白了。只是为可能在我这里遇到相同思维障碍的其他人提供答案,这就是我的问题。 在我的脑海中,我认为我必须先将值以某种方式写入到模板缓冲区中,然后再将它们写入到显示屏中。 @NicolBolas友善地指出,这是错误的。

命令glDrawArrays(在stencilTesting处于活动状态时)写入到显示器以及模板缓冲区。这样,对于接下来的所有内容,我们都将示例地板中的模板保存在缓冲区中,并可以使用它来评估是否要绘制像素。这样,我们可以有效地使第二个多维数据集仅在地板上绘制,而不能在其外部绘制。由于在绘制多维数据集之前将glStencilMask设置为全零,因此即使在动作上应用了模板测试,也要确保它不会影响模板缓冲区。如果有人偶然发现此问题,希望对您有所帮助。而且,如果这完全是胡说八道,请有人以我的想法为错误发表评论。