Jag*_*oly 2 opengl bitmask stencil-buffer
我正在3D引擎中渲染反射表面.我需要执行两次模板操作.首先,我通过深度测试绘制出反射表面,以找到表面的可见区域.然后我需要将模型绘制到一个G-Buffer中,它也被模板化以找到绘制我的天空盒的区域.
绘制曲面:总是绘制,写入#1位
绘制模型:仅在设置位#1时绘制,写入位#2
我如何使用OpenGL执行此操作?我不确定glStencilFunc ref和掩码值之间的关系,以及glDepthMask值.
文档是非常具体的,但如果您只是想创建然后激活蒙版,那么它并不总是直观或明显该怎么做.我用这些作为一个简单的起点......
将模板缓冲区清除为零并将1写入您绘制的所有像素.
void createStencilMask()
{
// Clear the stencil buffer with zeroes.
// This assumes glClearStencil() is unchanged.
glClear(GL_STENCIL_BUFFER_BIT);
// Enable stencil raster ops
// 1. Enables writing to the stencil buffer (glStencilOp)
// 2. If stencil test (glStencilFunc) fails, no frags are written
glEnable(GL_STENCIL_TEST);
// sfail GL_KEEP - keep original value if stencil test fails
// dpfail GL_KEEP - also keep if the stencil passes but depth test fails
// dppass GL_REPLACE - write only if both pass and you'd normally see it
// this writes the value of 'ref' to the buffer
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// func GL_ALWAYS - the stencil test always passes
// ref 1 - replace with ones instead of zeroes
// mask 1 - only operate on the first bit (don't need any more)
// Assumes glStencilMask() is unchanged
glStencilFunc(GL_ALWAYS, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)
调用上面的函数,绘制你的东西.您可以设置glDepthMask和glColorMask,这样实际上不会影响当前颜色/深度和场景,只会影响模板缓冲区.
仅绘制上一步中带有1s的像素.
void useStencilMask()
{
// Enable stencil raster ops
glEnable(GL_STENCIL_TEST);
// Just using the test, don't need to replace anything.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Only render if the current pixel stencil value is one.
glStencilFunc(GL_EQUAL, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)
绘制然后glDisable(GL_STENCIL_TEST)在完成后禁用测试.
现在关注你的问题......
此位是有点棘手,因为相同ref的值glStencilFunc()中使用两个模板测试和值来代替.但是,你可以用面具解决这个问题:
mask在glStencilFunc()测试/读取时忽略位.glStencilMask()从获取写入停止某些位.在您的情况下,您不需要屏蔽掉第一位,因为它已经设置好了.只需更新useStencilMask()到glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)和glStencilFunc(GL_EQUAL, 3, 1);.由于mask是1,只有第一位在测试平等使用.然而,整个ref3(即0b11)是写的.您可以使用glStencilMask(2)(这是0b10)停止写入第一位但它已经是一个因此无关紧要.
您还可以使用GL_INCR哪个将设置第二个位并删除第一个位.或者也许清楚一些并GL_ZERO用来标记你的位.