使用模板缓冲区勾画对象会给出错误的结果
Outlining an object using a stencil buffer give wrong result
我正在尝试使用模板缓冲区在模型后面绘制轮廓边框。
我正在使用 2 个渲染通道,首先渲染模型并使用 GL_ALWAYS
将 1
写入模板缓冲区,然后渲染使用 GL_NOTEQUAL
的 ref 值为 1
所以基本上只传递原始立方体之外的片段从而形成高亮。
我得到了奇怪的结果,轮廓没有完全渲染,当我充分移动我的相机时它完全消失,就好像放大立方体的模板测试根本没有通过一样。
这是渲染循环的要点(shader3 只是输出边框的颜色):
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClearStencil(0);
renderer.Clear();
...
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 100.0f);
UniformMat4f projectionUniform("u_Projection");
projectionUniform.SetValues(projection);
glm::mat4 view = camera.GetView();
UniformMat4f viewUniform("u_View");
viewUniform.SetValues(view);
modelUniform.SetValues(glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 0.0f, 0.0f)));
shader1.SetUniform(projectionUniform);
shader1.SetUniform(viewUniform);
shader1.SetUniform(modelUniform);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
renderer.Draw(model, shader1);
modelUniform.SetValues(glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 0.0f, 0.0f)), glm::vec3(1.1f, 1.1f, 1.1f)));
shader3.SetUniform(projectionUniform);
shader3.SetUniform(viewUniform);
shader3.SetUniform(modelUniform);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
renderer.Draw(model, shader3);
glEnable(GL_DEPTH_TEST);
}
我首先使用《孤岛危机》中的 nanosuit
模型进行了尝试,它的工作原理与我描述的一样,没有显示所有部件,最终在移动相机时消失了。我决定尝试一个简单的几何图形来测试这一点,并尝试勾勒出一个简单的立方体并得到相同的结果:
问题是在主循环结束时调用 glStencilMask(0x00);
。模板掩码的默认值为 0xff
(对于 8 位,请参见 glStencilMask
)。 OpenGL 是一个状态引擎。保持状态,直到再次更改(甚至超出帧)。
glClear
考虑颜色、深度和模板掩码的状态。如果模板掩码为 0x00
,则根本不会清除模板缓冲区。
设置模板掩码0xff
,然后清除模板缓冲区以解决问题:
glStencilMask(0xFF);
renderer.Clear();
我正在尝试使用模板缓冲区在模型后面绘制轮廓边框。
我正在使用 2 个渲染通道,首先渲染模型并使用 GL_ALWAYS
将 1
写入模板缓冲区,然后渲染使用 GL_NOTEQUAL
的 ref 值为 1
所以基本上只传递原始立方体之外的片段从而形成高亮。
我得到了奇怪的结果,轮廓没有完全渲染,当我充分移动我的相机时它完全消失,就好像放大立方体的模板测试根本没有通过一样。 这是渲染循环的要点(shader3 只是输出边框的颜色):
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClearStencil(0);
renderer.Clear();
...
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 100.0f);
UniformMat4f projectionUniform("u_Projection");
projectionUniform.SetValues(projection);
glm::mat4 view = camera.GetView();
UniformMat4f viewUniform("u_View");
viewUniform.SetValues(view);
modelUniform.SetValues(glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 0.0f, 0.0f)));
shader1.SetUniform(projectionUniform);
shader1.SetUniform(viewUniform);
shader1.SetUniform(modelUniform);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
renderer.Draw(model, shader1);
modelUniform.SetValues(glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 0.0f, 0.0f)), glm::vec3(1.1f, 1.1f, 1.1f)));
shader3.SetUniform(projectionUniform);
shader3.SetUniform(viewUniform);
shader3.SetUniform(modelUniform);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
renderer.Draw(model, shader3);
glEnable(GL_DEPTH_TEST);
}
我首先使用《孤岛危机》中的 nanosuit
模型进行了尝试,它的工作原理与我描述的一样,没有显示所有部件,最终在移动相机时消失了。我决定尝试一个简单的几何图形来测试这一点,并尝试勾勒出一个简单的立方体并得到相同的结果:
问题是在主循环结束时调用 glStencilMask(0x00);
。模板掩码的默认值为 0xff
(对于 8 位,请参见 glStencilMask
)。 OpenGL 是一个状态引擎。保持状态,直到再次更改(甚至超出帧)。
glClear
考虑颜色、深度和模板掩码的状态。如果模板掩码为 0x00
,则根本不会清除模板缓冲区。
设置模板掩码0xff
,然后清除模板缓冲区以解决问题:
glStencilMask(0xFF);
renderer.Clear();