参考:
1.小IVan这位年轻的大佬最近非常活跃:https://zhuanlan.zhihu.com/p/50535249
2.FOXhunt:https://zhuanlan.zhihu.com/p/21425792?refer=c_37032701
3.Volumetric Fog SIGGRAPH http://advances.realtimerendering.com/s2014/wronski/bwronski_volumetric_fog_siggraph2014.pdf
4.之前写的3D Cloud
1.何来体积雾
光在均匀的空气中直线传播,当遇到浑浊的空气,光线中的一部分能量会照射在小颗粒上,进而一部分光散射入眼睛。这是看见的光产生体积效果。
当然,也可以上面的说法也可能理解为体积光;
我对这两个概念效果的区分:
体积雾,是没有直接的光照,小颗粒反射的光线全部来自于间接光;
体积光,则是有明显的单一光照请向;
2.体积雾的实现方法
1.BillBoard贴片:介绍见参考 FOXhunt,算法参考《unity入门精要》顶点运动篇
2.径向模糊:【缺点:模糊的高光区必须再视野范围内】
1、先得到场景的需模糊的亮度;
2、将lightPos转换到屏幕空间,并用screen.xy-screenlight.xy得到模糊偏移的向量
3、再通过向量多次衰减偏移
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
// Calculate vector from pixel to light source in screen space.
half2 deltaTexCoord = (texCoord - ScreenLightPos.xy);
// Divide by number of samples and scale by control factor.
deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;
// Store initial sample.
half3 color = tex2D(frameSampler, texCoord);
// Set up illumination decay factor.
half illuminationDecay = 1.0f;
// Evaluate summation from Equation 3 NUM_SAMPLES iterations.
for (int i = 0; i < NUM_SAMPLES; i++)
{
// Step sample location along ray.
texCoord -= deltaTexCoord;
// Retrieve sample at new location.
half3 sample = tex2D(frameSampler, texCoord);
// Apply sample attenuation scale/decay factors.
sample *= illuminationDecay * Weight;
// Accumulate combined color.
color += sample;
// Update exponential decay factor.
illuminationDecay *= Decay;
}
// Output final color with a further scale control factor.
return float4( color * Exposure, 1);
}
3.光线追踪法
这种原理上,与物理原型贴近
虽然,再单一路线上,能看到的颗粒点是无数的,但我们可以来追踪一些关键点进行采样;
这用到了前面说的RayMarching的算法
在每个点上,我们又可以将它的光照信息分为:光照强度、散射、透光比、密度、阴影
1.光照强度
点光源:atten = 1/d^2;
平行光就可以忽略了
2.散射
当从光源发出的光线,照到颗粒上,只有小部分会反射入眼睛,很多光线都会被散射掉,比如:上图的绿箭头
float cosTheta = dot(lightDr,-rd);
float result = 1/(4*3.14)* (1 - g^2)/ pow(1 + g^2 -2*g* cosTheta, 1.5);
3.透光比
在空气中传播的光线,会随着距离的增加而衰减
可以向Fox说的简单写成:Out = Inexp(-cd);
再或者可以参考3D Cloud: Out = Inexp(-id^2);
4.密度
空气中的颗粒大多是非均质的,可以用一个3Dtexture 来采样控制密度值;
5.阴影
1)如不加阴影表现效果如普通fog,表现不出光照效果
2)物体遮挡阴影,很好的表现出阴影的遮挡,但每个采样点需多矩阵的变换
3)自身阴影,在每个采样点的位置向光源方向再做积分。