大气光散射实现

Posted

技术标签:

【中文标题】大气光散射实现【英文标题】:Atmospheric light scattering implementation 【发布时间】:2016-05-08 12:00:02 【问题描述】:

我正在尝试在 openGL 中实现大气散射。我正在使用这个“论文”作为教程: http://developer.amd.com/wordpress/media/2012/10/GDC_02_HoffmanPreetham.pdf

但是我在理解某些点和找出一些常数方面有一些困难。

基本上我必须实现这些公式:

首先我不知道 s 是眼睛到圆顶的距离还是眼睛到光源(这里是太阳)位置的距离。 角度 theta 也是如此,我无法确定它是从地面到太阳的角度还是到眼睛所注视的圆顶位置的角度。

其次在这张幻灯片中: 它告诉我天空会出现蓝色。我知道这是瑞利散射的原因,但有些事情我无法理解。上面公式中的所有计算都给了我一个标量:所以当我将它乘以标量时,基本上是 vec3(1,1,1) 的太阳白光如何变成蓝色,它只会变成灰度因为我将得到结果,例如 vec3(0.8,0.8,0.8)。我的意思是,如果出现一些不同的天空颜色,我必须将太阳光与 vec3 相乘以不同地改变 RGB 值。

现在我在实现我的着色器时遇到了一些困难。 这是天空着色器的代码:

#version 330

in vec3 vpoint;

in vec2 vtexcoord;


out vec2 uv;


out vec3 atmos;


uniform mat4 M;

uniform mat4 V;

uniform mat4 P;


mat4 MVP = P*V*M;



//uniform vec3 lpos;

vec3 lpos = vec3(100,0,0);

uniform vec3 cpos;



vec3 br = vec3(5.5e-6, 13.0e-6, 22.4e-6);

vec3 bm = vec3(21e-6);





float g = -0.75f;


vec3 Esun = vec3(2000,2000,2000);




vec3 Br(float theta)
return 3/(16*3.14) * br * (1+cos(theta)*cos(theta));




vec3 Bm(float theta)
return 1/(4*3.14) * bm * ((1 - g)*(1 - g))/(pow(1+g*g-
2*g*cos(theta),3/2));




vec3 atmospheric(float theta, float s)
return (Br(theta)*Bm(theta))/(br+bm) * Esun * (1- exp( -(br+bm)*s ));




void main() 

gl_Position = MVP * vec4(vpoint, 1.0);
uv = vtexcoord;

vec3 domePos = vec3(M*vec4(vpoint,1.0));

vec3 ldir = lpos - domePos;

float s = length(domePos-cpos);
float theta = acos(dot(normalize(ldir-domePos),normalize(domePos-
cpos)*vec3(1,1,0)));

atmos = atmospheric(theta,s)*1000000*5;


我没有得到预期的结果,这就是我得到的:

我只有蓝色,没有偏红的日落,但是太阳很低,根据我看过的不同教程,我应该在太阳落山时看到一些偏红的颜色。

【问题讨论】:

"太阳的白光" 太阳不会发出白光。 @JimZer 只是一个赌注(懒得分析你的代码)在太阳附近你的照明过饱和(远高于图像颜色深度)所以它被截断为白色。您应该将所有通道截断为单个向量,而不是每个通道。也看看我的散射***.com/a/19659648/2521214 简单一点 【参考方案1】:

警告我不是这个领域的专家,对此持保留态度。

这几乎说明了一切。

s 是顶点/像素与相机之间的距离。θ 是太阳与视线之间的角度。

为了计算 θ,您需要知道“黄线”和“视线”。 后者是普通的着色器数学;前者只是表达太阳在天空中有多高的一种方式。您可以将其建模为从太阳到地面上某个点的射线。


上面的所有公式都给出了向量。L0 是一个向量。Esun 也是一个向量。

幻灯片基本上说辐射度辐照度(Esun)等物理概念在光谱上是连续的,应该使用光谱功率分布来描述灯光和颜色。 然而,一种更快的方法是仅对光谱的三个点进行数学运算,即 R、G 和 B 波长的一个点。 在实践中,这表示 Esun 是一个向量,用于描述三个 RGB 波长的太阳辐照度。

天空的蓝色来自参数βR,它取决于θ,它取决于“视线”,它取决于片段的高度天空被染上了颜色。

【讨论】:

很好,我可以更好地理解。但是我只有蓝色,没有红色的日落,但是太阳很低,根据我看过的不同教程,当太阳下山时,我应该会看到一些红色的颜色。我用我能得到的东西更新我的帖子:你有什么想法吗?

以上是关于大气光散射实现的主要内容,如果未能解决你的问题,请参考以下文章

程序化天空盒过程记录01:日月 天空渐变 大气散射

大气散射 GPU Gems2 Chapter 16. Accurate Atmospheric Scattering

GLSL 大气散射不随变换缩放

大气散射 Aerial Perspective

案例学习——Unity基于体绘制的大气散射shader

图像去雾基于matlab颜色衰减先验图像去雾含Matlab源码 2036期