如何实现地面雾GLSL着色器

时间:2014-02-04 10:12:34

标签: opengl glsl shader

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

我无法理解等式中的哪一部分会导致这种情况。

对此有何想法?

编辑:这是我正在寻找的效果: image1 image2

2 个答案:

答案 0 :(得分:5)

这是大气散射的一个非常标准的应用。

通常在体积照明的保护伞下进行讨论,其涉及通过不同介质(例如烟雾,空气,水)的光透射。在尖端的基于着色器的图形中,这可以使用光线行进实时实现,或者如果只有一个统一的参与介质(在这种情况下,雾只适用于空气),简化为集成一段距离。

通常你会通过参与的媒体进行射线游行以确定光传输的属性,但是这个应用程序被简化为假设一种具有明确定义的分布特征的媒介,而你混淆的系数来自于。雾的密度随距离呈指数变化,这是b控制的,同样它也随高度变化( 未显示 在等式中直接在之下。

http://www.iquilezles.org/www/articles/fog/for00.png

然而,本文对讨论所介绍的是系数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

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

LaTeX Equation

此附加表达式控制密度相对于海拔高度。根据着色器的实现来判断,您没有正确实现第二个表达式。 camFrag.z很可能 海拔高度,而是深度。此外,我不明白为什么要将它乘以b系数。

答案 1 :(得分:4)

我找到了一个方法,可以提供我想要的结果。

Eric Lengyel的这篇文章描述了这个方法:[link] http://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf

它解释了如何使用密度和高度参数创建雾层。您可以飞过它,它会逐渐将所有几何体混合在雾上方。