【发布时间】:2017-01-16 17:36:25
【问题描述】:
您可以跳至底部的 TL;DR 以获取结论。我更愿意提供尽可能多的信息,以帮助进一步缩小问题范围。
我一直在处理我一直在研究的热雾效应。 这是我正在考虑的那种效果,但由于这是一个相当通用的系统,它适用于任何所谓的屏幕空间折射: 雾霾效应不是我的问题所在,因为它只是采样坐标的失真,而是与采样的内容有关。我的第一种方法是将失真渲染到另一个渲染目标。这种方法相当成功,但如果您以前处理过屏幕空间纹理,则很容易预见到它的主要缺点。问题是由于采样坐标的偏移,如果一个物体在折射镜的前面,它的边缘将被纳入折射计算。 如您所见,当所有几何图形都是环境(无深度测试)或背面几何图形时,它看起来很好。 这里有一个比折射镜更近的立方体。正如你所看到的,这种效果我称之为更接近几何体的出血。
相关着色器代码供参考:
/* transparency.frag */
layout (location = 0) out vec4 out_color; // frag color
layout (location = 1) out vec4 bright; // used for bloom effect
layout (location = 2) out vec4 deform; // deform buffer
[...]
void main(void) {
[...]
vec2 n = __sample_noise_texture_with_time__{};
deform = vec4(n * .1, 0, 1);
out_color = vec4(0, 0, 0, .0);
bright = vec4(0.0, 0.0, 0.0, .9);
}
/* post_process.frag */
in vec2 texel;
uniform sampler2D screen_t;
uniform sampler2D depth_t;
uniform sampler2D bright_t;
uniform sampler2D deform_t;
[...]
void main(void) {
[...]
vec3 noise_sample = texture(deform_t, texel).xyz;
vec2 texel_c = texel + noise_sample.xy;
[sample screen and bloom with texel_c, gama corect, output to color buffer]
}
为了解决这个问题,我尝试了一种涉及比较深度分量的技术。为此,我让透明对象像这样写它的 frag_depth tp 我的变形缓冲区的 z 分量
/* transparency.frag */
[...]
deform = vec4(n * .1, gl_FragCoord.z, 1);
[...]
然后在后处理着色器中快速检查一下确定前面是什么。
[...]
float dist = texture(depth_t, texel_c).x;
float dist1 = noise_sample.z; // what i wrote to the deform buffer z
if (dist + .01 < dist1) { /* do something liek draw debug */ }
[...]
这有点用,但当我离开时就坏了,即使我线性化了深度值并比较了距离。 编辑 3:为深度测试阶段添加了更好的屏幕截图 (在黄色的地方,它正在对前面的东西进行采样,我懒得让它也渲染多边形,所以我把它们画了进去) (这里证明它在更远的地方部分未能通过深度比较测试)
我还通过另一种技术获得了一些“乐趣”,我将颜色缓冲区直接传递给透明度着色器,并让它将样本输出到它的颜色输出。理论上,如果场景是 Z 排序的,这应该会产生所需的结果。我会让你来评判。 (我对出现的模式有一些猜测,因为它们类似于 GPU 的光栅化模式,但这并不是很相关,因为“解决方案”比任何事情都更加绝望)
TL;DR 和正式问题:根据我的知识,我尝试了一些技术,但找不到太多关于该主题的文献。所以我的问题是:您如何将 sch 效果实现为热雾/失真(我可能会添加不覆盖整个屏幕)并且是否有关于该主题的文献。有关我要查看哪种效果的参考,请参阅我的《守望先锋》屏幕截图和游戏中的所有其他类似效果。
为了完整起见,我还想提一下,我正在运行 OpenGL 4.5(在 Windows 上),大多数着色器都是 4.00 版,并且正在使用自定义引擎。
编辑:如果您想了解有关引擎软件部分的信息,请随时询问。我没有包含任何内容,因为我认为它不相关,但我很乐意提供规范和代码 sn-ps 以及更多按需着色器。
编辑 2:我想我还想提一下,这可以通过使用第二个渲染通道和一个剪切平面来实现,但是,这将是昂贵的并且感觉没有必要,因为视点是相同的。可能这是唯一的解决方案,但我不这么认为。
提前感谢您的回答!
【问题讨论】:
-
会不会是你写的深度分辨率不好?你用什么纹理来存储中间深度? GL_LUMINANCE16?我希望您不要将深度转储到 8 位通道中并稍后进行比较。
-
@Harish 不,不幸的是不是这样,我对所有深度缓冲区都使用 GL_DEPTH_COMPONENT32 格式,这解决了我过去遇到的所有 z 战斗问题。
标签: opengl graphics glsl rendering shader