-
Notifications
You must be signed in to change notification settings - Fork 6
Voxel cone tracing
其实体素化的过程可以理解为将多个切片的光栅化组合而成. 关闭背面剔除后,只需要从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的时候处理了一下.
整个光照计算可以放到compute shader里做. 光照流程和对普通gbuffer的处理没有什么不同.
- 因为在texture3d空间里 天然的划分了cluster, 所以对灯光的剔除其实也可以提前做好.
- 阴影可以用shadowmap 分辨率不用太高. 不过我采用的是直接在texture3d空间里直接对体素的灯光方向进行光线步进, 如果遇到其他不为空的体素,就说明光线被遮挡. 顺便根据遮挡体素到光源的距离比上受光计算的体素到光源的距离,可以用于计算软阴影.这种方法写起来在流程上比shadowmap简单(直接一个raymarch函数结束),但是过于计算量有点大(步进步长没法优化, 不然会穿过体素),导致我用512分辨率的texture3d时显卡直接超时报错.当然256分辨率的效果已经很不错了,再大你也上不了1024
- 做完光照后,如果追求效果,其实还可以来一次间接光照计算,具体做法就是直接cone trace,等于对自己做gi...具体做法往后看.
大多数vct 在这步都通过各向异性过滤 downsample到下一层. 不过我偷懒直接用的dx11的GenerateMips, 估计是个box filter, 也没什么好写的...
在完成前面那些步骤以后,才到了真正进行间接光照的计算. 具体流程可以参考各大vct的实现,其实大家都一样..
-
漫反射的间接光主要靠几个圆锥模拟半球积分. 需要注意的是在计算过程ao也是顺便求的.虽然不是很科学,不过能用
-
镜面反射的间接光根据粗糙度调整cone的角度, 效果非常不错,个人感觉达到了Stochastic SSR的那种效果, 关键不受屏幕空间信息的约束!
-
ao我直接作用在间接光上, 也看到别人会输出到 blend阶段 进行
Cdst = Csrc * Asrc + Cdst * Asrc
相关论文到处都是,我就简单发几个涉及具体实现的参考
http://simonstechblog.blogspot.com/2013/01/implementing-voxel-cone-tracing.html