glStencilFunc():为什么 GL_ALWAYS != GL_EQUAL union GL_NOTEQUAL?

glStencilFunc(): why is GL_ALWAYS != GL_EQUAL union GL_NOTEQUAL?

我希望能够将我的后处理图像传递剪辑到特定区域,这样模糊等效果只会影响这些区域

为了做到这一点,我使用模板缓冲区,我的管道如下:

  1. 仅将一些对象渲染到模板缓冲区,写入 1s
  2. 渲染一些模板值等于 1 的对象(这可行)
  3. 渲染模板缓冲区中的一些对象
  4. 运行 后处理通道(通过使用前 3 步的图像作为绑定纹理绘制四边形),其中模板值等于 1(或始终,取决于我的效果的属性)

我得到的结果:

令我吃惊的是,用 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 到一个小部件中,并且模板测试仍然处于活动状态,并且附加了另一个模板缓冲区:这就是屏幕变黑的原因。

结论:当你使用框架时总是将上下文恢复到它之前的状态