Skip to content

Voxel cone tracing

nujuxtsun edited this page Jul 23, 2019 · 1 revision

流程

1. 体素化

其实体素化的过程可以理解为将多个切片的光栅化组合而成. 关闭背面剔除后,只需要从3个轴向进行绘制就行了. 绘制完保存到texture3d中. 其中albedo 和 normal 都是必要的,其次材质信息也可以带入 比如 roughness, metallic. 这里有一点很重要的是: 在体素范围内可能包含了不同颜色不同方向的图元,需要对结果进行混合. 具体做法是将alpha通道用作记录体素写入数量, 每次写入就需要进行

dst.rgb = (dst.rgb * dst.a + src.rgb) / (dst.a + 1);

的操作. 然后因为d3d11在ps中只允许RWTexture3D, 所以 只能将信息再从float4 转成int保存下来, 每次运算都需要经历解码编码. 还有需要注意一个保守光栅化的问题, 这个网上到处都是随便搜一下就好了,dx12有对保守光栅化的支持.

顺便在实现vct的时候建议先写一个体素化的绘制展示(虽然后面用不到).在对体素化进行单元测试时很有帮助(你看大部分人的vct都会把voxels的绘制给展示出来).注意两个体素之间的面不用绘制.

整个体素化感觉和绘制gbuffer是一样的, 我也确实把绘制流程放在了gbuffer的shader里.仅在输出到texture的时候处理了一下.

2. 体素的光照

整个光照计算可以放到compute shader里做. 光照流程和对普通gbuffer的处理没有什么不同.

  1. 因为在texture3d空间里 天然的划分了cluster, 所以对灯光的剔除其实也可以提前做好.
  2. 阴影可以用shadowmap 分辨率不用太高. 不过我采用的是直接在texture3d空间里直接对体素的灯光方向进行光线步进, 如果遇到其他不为空的体素,就说明光线被遮挡. 顺便根据遮挡体素到光源的距离比上受光计算的体素到光源的距离,可以用于计算软阴影.这种方法写起来在流程上比shadowmap简单(直接一个raymarch函数结束),但是过于计算量有点大(步进步长没法优化, 不然会穿过体素),导致我用512分辨率的texture3d时显卡直接超时报错.当然256分辨率的效果已经很不错了,再大你也上不了1024
  3. 做完光照后,如果追求效果,其实还可以来一次间接光照计算,具体做法就是直接cone trace,等于对自己做gi...具体做法往后看.

3. 建立mipmap

大多数vct 在这步都通过各向异性过滤 downsample到下一层. 不过我偷懒直接用的dx11的GenerateMips, 估计是个box filter, 也没什么好写的...

4. 计算场景间接光照

在完成前面那些步骤以后,才到了真正进行间接光照的计算. 具体流程可以参考各大vct的实现,其实大家都一样..

  1. 漫反射的间接光主要靠几个圆锥模拟半球积分. 需要注意的是在计算过程ao也是顺便求的.虽然不是很科学,不过能用

  2. 镜面反射的间接光根据粗糙度调整cone的角度, 效果非常不错,个人感觉达到了Stochastic SSR的那种效果, 关键不受屏幕空间信息的约束!

  3. ao我直接作用在间接光上, 也看到别人会输出到 blend阶段 进行

    Cdst = Csrc * Asrc + Cdst * Asrc

参考

相关论文到处都是,我就简单发几个涉及具体实现的参考

http://simonstechblog.blogspot.com/2013/01/implementing-voxel-cone-tracing.html

https://github.com/jose-villegas/VCTRenderer