atomsphere scattering

最近花了一段时间在atomsphere scattering 上面. 我的目标是实现一个很高效的,有着良好日出,日落表现的室外环境, 而且不考虑支持外太空. 

http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html
http://hyperphysics.phy-astr.gsu.edu/hbase/atmos/blusky.html
https://software.intel.com/en-us/blogs/2013/06/26/outdoor-light-scattering-sample
http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf
http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf             a practical analytic model for daylight
http://etd.dtu.dk/thesis/58645/imm2554.pdf                               Real Time Rendering of Atmospheric Scattering Effects for Flight Simulators

在研究了上面的论文和例子后, 我发现各家实现的不同点主要在光学深度的积分上.

gpugems 2 chapter 16 , O'Neil 的实现中, 采用梯形来积分从而逼近真实效果. 这种方法. 在sig93_nis中也有提及, 是其的一个优化版本, 

虽然O'Neil 的优化已经做得非常好, 使得积分时需要的采样数已经降低到很低, 而且是在vertex shader 中实现, 但是这种实现不能满足我的需求. 

1. 你需要对暴露在大气中的所有物体均实现scattering 相关的代码. 比如. sky , terrain , sea, etc. 

2. vertex shader 中, 如果顶点数量过多, 计算量也会非常大. 

 

我的想法是: 既然大气散射发生在所有存在大气的地方, 那么, 我应该在post process 阶段, 全屏渲染. 从而和场景对象的逻辑脱离开来. 

而且, 可以将积分独立出来, 将积分结果渲染到一个低分辨率的浮点纹理中, 在post process 阶段, 通过对这个纹理进行采样,获得积分结果来优化性能. 

 

分析 cry engine 的时候, 也可以看出, cry engine 也是类似的做法, 但是其采样纹理是在CPU计算的. 

 

我最后决定采用Nielsen 所描述的物理模型和模拟思路. 因为其抛弃了积分. 取代积分的是采用了两个海拔(水平, 垂直)的平均光学深度,并通过root(5, h)的曲线进行线性插值,

在曲线上逼近真实的光学深度积分结果. (这里他所提供的方程没有任何物理,数学意义, 仅仅只是一个数值逼近的解决方法), 这一做法满足我对于性能的需求. 

 

于是我开始了自己的实现之路, 虽然其论文中的相关描述非常清晰, 但是我的道路却充满曲折. 

在折腾了近一周的零散时间后: 这是我的第一个结果: 

日出时分的, 看起来还像那么回事???? 不,  他不正常. 此时我输入的参数中, 理论上在靠近太阳和海平面的地方是橙色的天空, 而天空顶端应该是偏蓝色的!

 

// 一直忙于其它事情, 间间断断地偶尔弄下代码, 这个模型上个月已经实现. 

效果如下:

但是不幸的是, 在输入了各种参数后, 依然没有满足我的要求.  我希望的是在日出,日落时分, 太阳的底部能有更好的Mie散射. 比如下图中右边的效果. 

在分析了散射方程后, 得出的结论是: Nielsen 忽略光学深度的积分, 导致对于大环境的散射, 光学深度过于单一. 

 

posted @ 2014-12-25 10:38  访问异常  阅读(444)  评论(0编辑  收藏  举报