体积雾——理论篇

参考:
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)自身阴影,在每个采样点的位置向光源方向再做积分。

你可能感兴趣的:(体积雾——理论篇)