opengl 如何实现地面雾GLSL着色器

2uluyalo  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(340)

我正在尝试为我的地形渲染引擎实现一个地面雾着色器。本文介绍了这项技术: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是从照相机到片段的向量的垂直分量

我不明白是什么原因造成的。
有什么想法吗?
编辑:以下是我想要的效果:image1image2

pnwntuvh

pnwntuvh1#

这是大气散射的一个相当标准的应用。
它通常在体积照明的保护伞下进行讨论,这涉及到光通过不同介质(* 例如 * 烟雾、空气、水)的透射率。在尖端的基于着色器的图形中,这可以通过使用光线行进实时实现,或者如果只有一个均匀的参与介质(在这种情况下-雾仅适用于空气),简化为在一定距离上的积分。
通常情况下,您会通过光线行进穿过参与介质,以确定光传输的属性,但本应用程序被简化为假设介质具有明确的分布特征,这就是您所困惑的系数的来源。雾的密度随距离呈指数变化,这就是b所控制的。同样,它也随高度变化(*在下面的等式中未示出)。

(来源:iquilezles.org
然而,本文在讨论中引入的是名称不佳的系数ab。这些系数控制内散射和消光。作者反复将***消光***系数称为 * 消光 *。这对我来说真的没有意义--希望这只是因为英语不是作者的母语。消光可以被认为是光被吸收的速度,它描述了一种介质的不透明度。如果你想为这一切提供更多的理论基础,可以看看the following paper

记住这一点,再看一下您文章中的代码:

vec3 applyFog( in vec3  rgb,      // original color of the pixel
               in float distance, // camera to point distance
               in vec3  rayOri,   // camera position
               in vec3  rayDir )  // camera to point vector
{
    float fogAmount = c*exp(-rayOri.y*b)*(1.0-exp(-distance*rayDir.y*b))/rayDir.y;
    vec3  fogColor  = vec3(0.5,0.6,0.7);
    return mix( rgb, fogColor, fogAmount );
}

你可以看到这个代码中的c实际上是原始方程中的a

更重要的是,这里还有一个表达式:

这个额外的表达式控制高度的密度。从你的着色器实现来看,你没有正确实现第二个表达式。camFrag.z很可能***不是***高度,而是深度。而且,我不明白你为什么要把它乘以b系数。

3xiyfsfu

3xiyfsfu2#

我找到了一种方法,它给出了我想要的结果。
Eric Lengyel的这篇文章中描述了该方法:http://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
它解释了如何用密度和高度参数创建雾层。你可以飞过它,它逐渐混合雾上方的所有几何图形。

相关问题