Я реализую метод OIT из этой статьи , и я просто не могу получить правильные результаты, основываясь на его эталонном изображении .Когда я пытаюсь воспроизвести его ссылку (ну, не ТОЧНО ), получается следующее:
![enter image description here](https://i.stack.imgur.com/R0j0B.jpg)
Issue
Таким образом, результат раскрытия выглядит хорошо, но его накопление является неправильным.Для начала, нет проверки глубины.Синие и красные квадраты должны быть позади или перед желтым квадратом.Также нет никакого альфа-смешения с черным фоном из-за трех средних квадратов, все из которых имеют альфа-значения 0,75.
Тогда в комбинированном проходе также не похоже, чтобы использовать текстуру раскрытия для определения глубины.каждого объекта.
Из того, что я могу сказать с большей частью кода OpenGL, является то, что порядок выполнения имеет решающее значение, и я при отладке (продолжался в течение трех дней), я получаю разные результаты при перемещении чего-то вродеgl.DepthMask(false)
или gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
вверх на одну строку.
Код
func (o *OpenGL) draw() {
gl.ClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
// DRAW OPAQUE FIRST (although the issue isn't really here, I just put it in incase)
gl.BindFramebuffer(gl.FRAMEBUFFER, o.opaqueFBO)
gl.DrawBuffer(gl.COLOR_ATTACHMENT0)
gl.Enable(gl.DEPTH_TEST)
gl.DepthMask(true)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.Disable(gl.BLEND)
gl.UseProgram(o.opaqueShader)
// Set uniforms
// Draw opaque objects
gl.UseProgram(0)
// THEN TRANSPARENT
gl.BindFramebuffer(gl.FRAMEBUFFER, o.transparentFBO)
gl.DrawBuffers(2, &[]uint32{gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1}[0])
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.ClearBufferfv(gl.COLOR, 0, &[]float32{0, 0, 0, 1}[0])
gl.ClearBufferfv(gl.COLOR, 1, &[]float32{1, 1, 1, 1}[0])
gl.Enable(gl.DEPTH_TEST)
gl.DepthMask(false)
gl.Enable(gl.BLEND)
gl.BlendFunci(0, gl.ONE, gl.ONE)
gl.BlendFunci(1, gl.ZERO, gl.ONE_MINUS_SRC_ALPHA)
gl.UseProgram(o.transparentShader)
// Set uniforms
// Draw opaque objects
gl.UseProgram(0)
// COMPOSITE PASS
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
gl.Disable(gl.DEPTH_TEST)
gl.Disable(gl.BLEND)
gl.UseProgram(o.compositeShader)
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, o.transparentTex0)
gl.Uniform1i(uniformLocation(o.compositeShader, "ColorTex0\x00"), int32(0))
gl.ActiveTexture(gl.TEXTURE1)
gl.BindTexture(gl.TEXTURE_2D, o.transparentTex1)
gl.Uniform1i(uniformLocation(o.compositeShader, "ColorTex1\x00"), int32(1))
gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, gl.PtrOffset(0))
gl.BindVertexArray(0)
gl.UseProgram(0)
// RENDER A SPECIFIC TEXTURE FROM A FRAMEBUFFER. FOR TESTING THIS DRAWS OVER WHAT HAS ALREADY BEEN DRAWN.
// A.
// o.renderFramebuffer(o.transparentFBO, o.transparentTex0)
// B.
// o.renderFramebuffer(o.transparentFBO, o.transparentTex1)
}
func (o *OpenGL) renderFramebuffer(fbo uint32, tid uint32) {
// FBO DEBUGGER
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
gl.UseProgram(o.framebufferShader)
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, tid)
gl.Uniform1i(uniformLocation(o.framebufferShader, "Texture\x00"), int32(0))
// draw fullscreen quad
gl.UseProgram(0)
o.window.SwapBuffers()
}
В нижней части функции рисования находятся две функции, которые я использовал для генерации изображений раскрытия и накопления из моегоссылка на тестирование.
Шейдеры
Вот фрагментный шейдер из o.transparentShader
#version 450 core
layout(location=0) in vec2 vTexCoord;
uniform vec4 uColor;
layout(location=0, index=0) out vec4 oFragData0;
layout(location=0, index=1) out vec4 oFragData1;
float w(float z, float a) {
return a * max(
pow(10.0, -2.0),
min(
3.0 * pow(10.0, 3.0),
10.0 /
(
pow(10.0, -5.0) +
pow(abs(z) / 5.0, 2.0) +
pow(abs(z) / 200.0, 6.0)
)
)
);
}
void main() {
vec4 Ci = uColor;
float ai = Ci.a;
float zi = gl_FragCoord.z;
float wresult = w(zi, ai);
oFragData0 = vec4(Ci.rgb * wresult, ai);
oFragData1.r = ai * wresult;
}
И фрагментный шейдер из o.compositeShader
#version 450 core
layout(location=0) out vec4 outColor;
uniform sampler2D ColorTex0;
uniform sampler2D ColorTex1;
out vec4 oFragColor;
void main() {
vec4 accum = texelFetch(ColorTex0, ivec2(gl_FragCoord.xy), 0);
float r = accum.a;
accum.a = texelFetch(ColorTex1, ivec2(gl_FragCoord.xy), 0).r;
vec4 transparentColor = vec4(accum.rgb / clamp(accum.a, 1e-4, 5e4), r);
oFragColor = transparentColor * (1.0 - r);
}
Заключительная записка
Я убрал все проверки ошибок, чтобы вопрос оставался минимальным.Я могу подтвердить, что нет ошибок с шейдерами, вложениями кадрового буфера или gl.GetError()
во время выполнения моих тестовых выходных данных.
Я также удалил большую часть кода, относящегося к рисованию непрозрачных объектов, так как эта проблемао прозрачных объектах.
Обновление № 1 (тестирование без кадровых буферов)
В качестве отчаяния я удалил весь код, связанный с FBO, и натолкнулся на некоторые интересные результаты, касающиесясмешивание ...
DEPTH_TEST включен |BLEND отключен |DEPTH_MASK false
DEPTH_TEST отключен |BLEND включен |DEPTH_MASK false
DEPTH_TEST включен |BLEND включен |DEPTH_MASK false ![enter image description here](https://i.stack.imgur.com/bmp8k.jpg)
Как бы нелепо это ни звучало, на самом деле похоже, что можно проводить смешивание и тестирование глубины по отдельности, но при объединении это просто немногои то и другое сдается ... Может ли это быть как-то связано с функциями смешивания?
Обновление № 2 (почти идеальные результаты, основанные на справочнике NVidia)
С несколькими совершенно новыми отладкамиинструменты и лучшее понимание того, как работает OIT, я смог очень приблизиться к результатам, на которые я надеюсь.Последний недостаток заключается в том, что непрозрачные объекты (масштабированный желтый квадрат и повернутый голубой) затемнены.
![enter image description here](https://i.stack.imgur.com/hygUu.jpg)
Я получил это, настроивЗначения BlendFunc и изучение нескольких сложных уроков о том, когда использовать какую из этих пар:
texture
против texelFetch
GL_TEXTURE_2D
против GL_TEXTURE_RECT
RGBA16F
против RGBA
ONE_MINUS_SRC_ALPHA
против ONE_MINUS_SRC_COLOR
Я настоятельно рекомендую полностью понять различия, прежде чем пытаться MRT, Framebuffers или OIT.Каждая ссылка использовала различную комбинацию этих значений.
Обновление № 3 (окончательное)
Поэтому, полностью оторвавшись от всех ссылок и избегая попыток скопировать их код, я посмотрелна эталонном изображении из первого абзаца и просто применил его по-своему.
![enter image description here](https://i.stack.imgur.com/zF3EB.jpg)
Я собираюсь оставить этот вопрос на некоторое время, прежде чем яОтправьте ответ, потому что я все еще немного скептичен и хочу провести больше тестов (или, возможно, услышать от вас, ребята?).