我正在尝试为我的地形渲染引擎实现一个地面雾着色器。本文介绍了这项技术:http://www.iquilezles.org/www/articles/fog/fog.htm
其思想是考虑从摄像机到碎片的光线,并沿着该光线对雾密度函数进行积分。
以下是我的着色器代码:
# version 330 core
in vec2 UV;
in vec3 posw;
out vec3 color;
uniform sampler2D tex;
uniform vec3 ambientLightColor;
uniform vec3 camPos;
const vec3 FogBaseColor = vec3(1., 1., 1.);
void main()
{
vec3 light = ambientLightColor;
vec TexBaseColor = texture(tex,UV).rgb;
//***************************FOG********************************************
vec3 camFrag = posw - camPos;
float distance = length(camFrag);
float a = 0.02;
float b = 0.01;
float fogAmount = a * exp(-camPos.z*b) * ( 1.0-exp( -distance*camFrag.z*b ) ) / (b*camFrag.z);
color = mix( light*TexBaseColor, light*FogBaseColor, fogAmount );
}
第一件事是,我不明白如何选择a和B以及它们在雾密度函数中的物理作用是什么。
然后,结果不是我所期望的...我有一个地面雾,但fogAmount从0到1的过渡总是以摄影机高度为中心。我尝试了很多不同的a和b,但当我在摄影机高度没有过渡时,我在所有地形上要么有全雾,要么没有雾。
我检查了我使用的数据,一切都是正确的:
- camPos.z是照相机的高度
- camFrag.z是从照相机到片段的向量的垂直分量
2条答案
按热度按时间pnwntuvh1#
这是大气散射的一个相当标准的应用。
它通常在体积照明的保护伞下进行讨论,这涉及到光通过不同介质(* 例如 * 烟雾、空气、水)的透射率。在尖端的基于着色器的图形中,这可以通过使用光线行进实时实现,或者如果只有一个均匀的参与介质(在这种情况下-雾仅适用于空气),简化为在一定距离上的积分。
通常情况下,您会通过光线行进穿过参与介质,以确定光传输的属性,但本应用程序被简化为假设介质具有明确的分布特征,这就是您所困惑的系数的来源。雾的密度随距离呈指数变化,这就是
b
所控制的。同样,它也随高度变化(*在下面的等式中未示出)。(来源:iquilezles.org)
然而,本文在讨论中引入的是名称不佳的系数
a
和b
。这些系数控制内散射和消光。作者反复将***消光***系数称为 * 消光 *。这对我来说真的没有意义--希望这只是因为英语不是作者的母语。消光可以被认为是光被吸收的速度,它描述了一种介质的不透明度。如果你想为这一切提供更多的理论基础,可以看看the following paper。记住这一点,再看一下您文章中的代码:
你可以看到这个代码中的
c
实际上是原始方程中的a
。更重要的是,这里还有一个表达式:
这个额外的表达式控制高度的密度。从你的着色器实现来看,你没有正确实现第二个表达式。
camFrag.z
很可能***不是***高度,而是深度。而且,我不明白你为什么要把它乘以b
系数。3xiyfsfu2#
我找到了一种方法,它给出了我想要的结果。
Eric Lengyel的这篇文章中描述了该方法:http://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
它解释了如何用密度和高度参数创建雾层。你可以飞过它,它逐渐混合雾上方的所有几何图形。