glStencilFunc (): почему GL_ALWAYS! = GL_EQUAL union GL_NOTEQUAL? - PullRequest
1 голос
/ 06 мая 2019

Я хочу иметь возможность обрезать свои проходы постобработки изображения в определенных областях, чтобы эффекты, такие как размытие, влияли только на эти области

Для этого я использую буфер трафарета и мойконвейер выглядит следующим образом:

  1. Визуализация некоторых объектов только в буфер трафарета с записью 1с
  2. Визуализация некоторых объектов, значение трафарета которых равно 1 (это работает)
  3. Визуализация некоторых объектов, независимо от того, что находится в буфере трафарета.
  4. Выполнение проходов постобработки (путем рисования квадрата с изображением, полученным в результате предыдущего шага 3 в виде связанной текстуры), где значение трафарета равно 1 (или всегда, в зависимости от атрибута моих эффектов)

Результаты, которые я получаю:

  • Черное изображение, когда постобработка включает трафаретный буфер
  • «Хорошее» изображение, когда оно не
  • Изображение с ненулевыми значениями только вне масок, когда я изменяю `glStencilFunc (GL_EQUAL, 1, 0xFF);` на `glStencilFunc (GL_NOTEQUAL, 1, 0x)FF); `

Меня поражает тот факт, что изображение, полученное с 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);
}

1 Ответ

1 голос
/ 13 мая 2019

Ответ: Я не восстановил контекст после рисования, например. отключить тестирование трафарета в конце моего прохода рендеринга. Я использую Qt, чтобы перетащить свой кадровый буфер в виджет, и тест трафарета все еще был активен с другим прикрепленным буфером трафарета: именно поэтому экран стал черным.

Вывод: Всегда восстанавливать контекст до его предыдущего состояния при использовании фреймворка

...