【问题标题】:How to implement a ground fog GLSL shader如何实现地面雾 GLSL 着色器
【发布时间】:2022-05-07 02:14:18
【问题描述】:

我正在尝试为我的地形渲染引擎实现一个地面雾着色器。 该技术在本文中有所描述: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以及它们在雾密度函数中的物理作用。

那么,结果不是我所期望的…… 我有一个地面雾,但从 0 到 1 的雾量的过渡始终以相机高度为中心。我尝试了很多不同的 a 和 b,但是当我在相机高度没有过渡时,我要么完全雾化,要么在所有地形上都没有雾化。

我检查了我使用的数据,一切都正确:

  • camPos.z 是我相机的高度
  • camFrag.z 是从相机到片段的向量的垂直分量

我无法理解方程式的哪一部分导致了这种情况。

对此有什么想法吗?

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

【问题讨论】:

    标签: opengl glsl shader


    【解决方案1】:

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

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

    通常,您会通过参与介质进行光线行进以确定光传输的属性,但此应用程序被简化为假设介质具有明确的分布特征,这就是您感到困惑的系数的来源.雾的密度随距离呈指数变化,这是b 所控制的,同样它也随高度而变化(未显示在下面的等式中)。

       
    (来源:iquilezles.org

    然而,本文引入讨论的是命名不佳的系数ab。这些控制内散射和消光。作者反复将 extinction 系数称为 extintion,这对我来说真的没有意义 - 希望这只是因为英语不是作者的母语。消光可以被认为是光被吸收的速度,它描述了介质的不透明度。如果您想了解所有这些的更多理论基础,请查看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 系数。

    【讨论】:

    • 我刚刚注意到 LaTeX 方程中的一个变量是错误的,它应该是-distance。但是考虑到在 Stack Overflow 和 Math 上使用 LaTeX 有多么困难,我什至不想费心去改变它。
    • 感谢安东您的帮助。 camFrag.z 是我的rayDir.y,我认为这是我的方向向量的垂直分量,不是吗?我的分母乘以b,因为它是exp(-b*Dy*t) 积分的结果,即exp(-b*Dy*t)/(-b*Dy)。事实上,我不知道为什么这个乘法从文章的着色器代码中消失了,因为作者之前提到过:link
    • 为什么你的 Z 分量和上向量有关? Z 通常在 GL 中向前。另外,camFrag 是否标准化?
    • 我的 camFrag 向量已标准化,Z 是我的上向量,因为我在 East North Up 系统中:link。我终于找到了一些 a 和 b 会产生某种阴霾,但绝对不是我想要的......(我编辑了我的第一篇文章以显示我正在寻找的东西)。有了这个等式,雾度太不透明了,我不知道如何管理过渡锐度和高度。我真的觉得这种方法旨在管理全球风景大气衰减,而不是固定高度的锐雾层。
    【解决方案2】:

    我找到了一种方法,可以提供我正在寻找的结果。

    方法在Eric Lengyel的这篇文章中描述:http://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf

    它解释了如何创建具有密度和高度参数的雾层。你可以飞过它,它会逐渐融合雾上方的所有几何体。

    【讨论】:

      猜你喜欢
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多