我正在this article实施OIT方法,而我似乎无法根据他的reference image获得正确的结果。当我尝试重现他的参考(好吧,而不是完全)时,它会出现如下:
因此,揭示输出看起来不错,但它的积累是完全错误的。首先,没有深度测试。蓝色和红色方块都应位于黄色方块的后面或前面。由于三个中间正方形都具有0.75个alpha值,因此也没有与黑色背景进行任何alpha混合。
然后在复合传递中,它似乎也没有使用揭示纹理来指示每个对象的深度。
从大多数OpenGL代码我可以看出,执行顺序是至关重要的,我在调试时(现在已经持续了三天),在移动诸如gl.DepthMask(false)
或{之类的内容时会得到不同的结果{1}}向上一行。
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
在绘图函数的底部是我用来从我的测试参考中生成revealage和accumu图像的两个函数。
以下是来自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);
}
没有错误。
我还删除了与绘制不透明对象有关的大部分代码,因为这个问题与透明对象有关。
作为一种绝望的行为,我已经删除了与FBO相关的所有代码,我发现了一些与混合相关的有趣结果......
启用DEPTH_TEST | BLEND禁用| DEPTH_MASK错误 禁用DEPTH_TEST |启用BLEND | DEPTH_MASK错误 已启用DEPTH_TEST |启用BLEND | DEPTH_MASK错误
听起来很荒谬,实际上看起来它可以分别进行混合和深度测试,但是当它结合起来时它只会做一点点然后放弃......这可能与混合有关功能
通过一些全新的调试工具以及对OIT如何工作的更好理解,我已经能够非常接近我希望的结果。最后的缺陷是不透明物体(缩放的黄色正方形和旋转的青色正方形)变暗。
通过调整BlendFunc值并学习一些关于何时使用其中每一对的一些重要课程,我做到了这一点:
gl.GetError()
vs texture
texelFetch
vs GL_TEXTURE_2D
GL_TEXTURE_RECT
vs RGBA16F
RGBA
vs ONE_MINUS_SRC_ALPHA
我强烈建议在尝试MRT,Framebuffers或OIT之前完全理解这些差异。每个引用都使用了这些值的不同组合。
因此,在完全疏远所有引用并避免尝试复制代码之后,我查看了第一段中的参考图像,并按照自己的方式实现了它。
在我提交答案之前,我会暂时离开这个问题,因为我仍然有点怀疑,我想要进行更多的测试(或者听听你们的答案?)。