glStencilFunc():为什么 GL_ALWAYS != GL_EQUAL union GL_NOTEQUAL?
glStencilFunc(): why is GL_ALWAYS != GL_EQUAL union GL_NOTEQUAL?
我希望能够将我的后处理图像传递剪辑到特定区域,这样模糊等效果只会影响这些区域
为了做到这一点,我使用模板缓冲区,我的管道如下:
- 仅将一些对象渲染到模板缓冲区,写入 1s
- 渲染一些模板值等于 1 的对象(这可行)
- 渲染模板缓冲区中的一些对象
- 运行 后处理通道(通过使用前 3 步的图像作为绑定纹理绘制四边形),其中模板值等于 1(或始终,取决于我的效果的属性)
我得到的结果:
- 后处理涉及模板缓冲区时的黑色图像
- 'Good' 没有的图片
- 当我将 `glStencilFunc(GL_EQUAL, 1, 0xFF);` 更改为 `glStencilFunc(GL_NOTEQUAL, 1, 0xFF); 时,仅在蒙版外具有非空值的图像;`
令我吃惊的是,用 glStencilFunc(GL_ALWAYS, 1, 0xFF);
获得的图像甚至不等于其他两个的并集:用 glStencilFunc(GL_EQUAL, 1, 0xFF);
的图像是全黑的。
这段代码有什么问题?
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, objectsTex, 0);
gl->glClear(GL_COLOR_BUFFER_BIT);
// ================= Masks ===================
gl->glEnable(GL_STENCIL_TEST);
gl->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color buffer writing
gl->glStencilFunc(GL_ALWAYS, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
gl->glStencilMask(MASKSBITPLANE); // Write values as is in the stencil buffer
gl->glClear(GL_STENCIL_BUFFER_BIT);
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getMaskObjects()){
renderBlankSceneObject(scobjptr, gl, glext);
}
// ================= Masked ===================
gl->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Enable color buffer writing
gl->glStencilFunc(GL_EQUAL, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl->glStencilMask(0x00); // Disable writing to the stencil buffer
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getMaskedObjects()){
renderSceneObject(scobjptr, gl, glext);
}
// ================= Raw objects ===================
gl->glDisable(GL_STENCIL_TEST);
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getRawObjects()){
renderSceneObject(scobjptr, gl, glext);
}
// ================= Postprocess ===================
auto& shaderEffects(renderGroup->shaderEffects());
if (renderGroup->areShaderEffectsMasked()){
gl->glEnable(GL_STENCIL_TEST);
gl->glStencilFunc(GL_EQUAL, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl->glStencilMask(0x00); // Disable writing to the stencil buffer
}
for (auto it(shaderEffects.begin()); it != shaderEffects.end(); ++it)
{
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentImageTex, 0);
gl->glClear(GL_COLOR_BUFFER_BIT);
// postprocess
gl->glUseProgram(shaderEffect->program().programId());
gl->glUniform1f(shaderEffect->m_timeLocation, m_time.elapsed());
gl->glActiveTexture(GL_TEXTURE0 + GLShaderEffect::PROCESSED_IMAGE_TEXTURE);
gl->glBindTexture(GL_TEXTURE_2D, processedTexture);
// some glUniform* calls
updateUniforms(gl, shaderEffect->ressourceClientsCollection());
// some glActiveTexture + glBindTexture calls
bindTextures(gl, shaderEffect->ressourceClientsCollection());
glext->glBindVertexArray(shaderEffect->vao());
gl->glDrawElements(GL_TRIANGLES, shaderEffect->elementsCount(), GL_UNSIGNED_INT, nullptr);
swap(currentImageTex, objectsTex);
}
答案:我画完后没有还原上下文,例如在我的渲染过程结束时禁用模板测试。
我使用 Qt 将我的帧缓冲区 blit 到一个小部件中,并且模板测试仍然处于活动状态,并且附加了另一个模板缓冲区:这就是屏幕变黑的原因。
结论:当你使用框架时总是将上下文恢复到它之前的状态
我希望能够将我的后处理图像传递剪辑到特定区域,这样模糊等效果只会影响这些区域
为了做到这一点,我使用模板缓冲区,我的管道如下:
- 仅将一些对象渲染到模板缓冲区,写入 1s
- 渲染一些模板值等于 1 的对象(这可行)
- 渲染模板缓冲区中的一些对象
- 运行 后处理通道(通过使用前 3 步的图像作为绑定纹理绘制四边形),其中模板值等于 1(或始终,取决于我的效果的属性)
我得到的结果:
- 后处理涉及模板缓冲区时的黑色图像
- 'Good' 没有的图片
- 当我将 `glStencilFunc(GL_EQUAL, 1, 0xFF);` 更改为 `glStencilFunc(GL_NOTEQUAL, 1, 0xFF); 时,仅在蒙版外具有非空值的图像;`
令我吃惊的是,用 glStencilFunc(GL_ALWAYS, 1, 0xFF);
获得的图像甚至不等于其他两个的并集:用 glStencilFunc(GL_EQUAL, 1, 0xFF);
的图像是全黑的。
这段代码有什么问题?
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, objectsTex, 0);
gl->glClear(GL_COLOR_BUFFER_BIT);
// ================= Masks ===================
gl->glEnable(GL_STENCIL_TEST);
gl->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color buffer writing
gl->glStencilFunc(GL_ALWAYS, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
gl->glStencilMask(MASKSBITPLANE); // Write values as is in the stencil buffer
gl->glClear(GL_STENCIL_BUFFER_BIT);
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getMaskObjects()){
renderBlankSceneObject(scobjptr, gl, glext);
}
// ================= Masked ===================
gl->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Enable color buffer writing
gl->glStencilFunc(GL_EQUAL, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl->glStencilMask(0x00); // Disable writing to the stencil buffer
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getMaskedObjects()){
renderSceneObject(scobjptr, gl, glext);
}
// ================= Raw objects ===================
gl->glDisable(GL_STENCIL_TEST);
for (const auto& scobjptr : renderGroup->getRenderGroupObjects().getRawObjects()){
renderSceneObject(scobjptr, gl, glext);
}
// ================= Postprocess ===================
auto& shaderEffects(renderGroup->shaderEffects());
if (renderGroup->areShaderEffectsMasked()){
gl->glEnable(GL_STENCIL_TEST);
gl->glStencilFunc(GL_EQUAL, 1, MASKSBITPLANE);
gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl->glStencilMask(0x00); // Disable writing to the stencil buffer
}
for (auto it(shaderEffects.begin()); it != shaderEffects.end(); ++it)
{
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, currentImageTex, 0);
gl->glClear(GL_COLOR_BUFFER_BIT);
// postprocess
gl->glUseProgram(shaderEffect->program().programId());
gl->glUniform1f(shaderEffect->m_timeLocation, m_time.elapsed());
gl->glActiveTexture(GL_TEXTURE0 + GLShaderEffect::PROCESSED_IMAGE_TEXTURE);
gl->glBindTexture(GL_TEXTURE_2D, processedTexture);
// some glUniform* calls
updateUniforms(gl, shaderEffect->ressourceClientsCollection());
// some glActiveTexture + glBindTexture calls
bindTextures(gl, shaderEffect->ressourceClientsCollection());
glext->glBindVertexArray(shaderEffect->vao());
gl->glDrawElements(GL_TRIANGLES, shaderEffect->elementsCount(), GL_UNSIGNED_INT, nullptr);
swap(currentImageTex, objectsTex);
}
答案:我画完后没有还原上下文,例如在我的渲染过程结束时禁用模板测试。 我使用 Qt 将我的帧缓冲区 blit 到一个小部件中,并且模板测试仍然处于活动状态,并且附加了另一个模板缓冲区:这就是屏幕变黑的原因。
结论:当你使用框架时总是将上下文恢复到它之前的状态