lightmap的shadowmask混合光照对于GPU Instancing的支持
2018-03-21 15:08
821 查看
项目的需求,开放视角要考虑DrawCall的开销,所以要是实现这个功能,这个功能已经完成一段时间了,在这里做个记录,由于项目是商用,故不能贴出源代码,只贴出实现思路,供大家交流,如有不对的地方还请指正。
GPU Instancing已经不是什么新技术了,其目的主要是为了提升绘制大量物体的渲染效率,从CPU和GPU层面减少重复性的工作,具体GPU Instancing的技术细节说明,本文不再赘述,感兴趣的同学可以在查看本文最后的扩展链接。
Unity在5.4版本开始引入了GPU Instancing,分为自动和手动两种方式,原生的 surface shader和stand shader都提供GPU Instancing的自动选项,只要在材质界面上勾选Enable GPU Instancing选项,无论手动或自动,大的前提是要Mesh和材质相同。
我们知道,任何通用的解决方案背后都会有或多或少的限制,这在程序设计上是说得通的,因此才会体现定制的价值。Unity也不例外,自动的GPU Instancing会有很多限制,比如:不支持static batch,不支持lightmap,等等。关于Unity GPU Instancing说明以及限制。请参照官方文档https://docs.unity3d.com/Manual/GPUInstancing.html
在项目的实际应用中,我们的场景中存在大量的静态植被都需要lightmap烘焙,如果自动不支持,显然我们就要考虑手动的方式,这正是本文的目的,Unity提供了两个底层的API来进行手动的GPUInstancing,分别是Graphics.DrawMeshInstanced和Graphics.DrawMeshInstancedIndirect。
有了实现的入口,接下来就是实现的思路和流程,首先要做lightmap的支持,如果不考虑shadowmask的情况下,这个问提还是很好解决的,就是把模型对应的lightmapScaleOffset传给shader做lightmap采样,在shader走uniry 的gi流程,模型行本身不做GPUInstancing处理,考虑到混合光照的情况,还要对shadowmask进行采样,所以就需要把shadowmask贴图和光照贴图都传给shader。
这里面在项目实际操作中,遇到了两个坑:
1:如果shadowmask是多张的情况,还要通过shadowmask对对象分组,就是在一张shadowmask贴图上都有哪些对象,而最终的分组长度则会直接影响GPUInstancing的批处理数量。
2:很多项目在Quality设置选项中,都会将shadow distance的值设置的很小,这是为了保证阴影的精度。如果绘制对象过于密集,由于是按shadowmask进行分组Instancing,单张shadowmask中对象在场景中很分散,对象所对应的阴影距离超出shadow distance设置的值,表现得效果就是,不分对象没有进行shadowmask采样,这个问题在目前还没有找到很好的解决办法,有哪位小伙伴有更好解决方案可以在下面留言。
最后再通过Graphics.DrawMeshInstanced或Graphics.DrawMeshInstancedIndirect每帧绘制对象,这里还有一个问题要注意就是官方对于Graphics.DrawMeshInstanced绘制对象的个数是有限制的,最高上限上限是1023,强迫症的表示很不爽。
这是1023颗草的效果,36个DrawCall。
最后要感谢leonwei博主,起初我就看了他的文章,才有了思路,原文在这 http://blog.csdn.net/leonwei/article/details/73274808
GPU Instancing已经不是什么新技术了,其目的主要是为了提升绘制大量物体的渲染效率,从CPU和GPU层面减少重复性的工作,具体GPU Instancing的技术细节说明,本文不再赘述,感兴趣的同学可以在查看本文最后的扩展链接。
Unity在5.4版本开始引入了GPU Instancing,分为自动和手动两种方式,原生的 surface shader和stand shader都提供GPU Instancing的自动选项,只要在材质界面上勾选Enable GPU Instancing选项,无论手动或自动,大的前提是要Mesh和材质相同。
我们知道,任何通用的解决方案背后都会有或多或少的限制,这在程序设计上是说得通的,因此才会体现定制的价值。Unity也不例外,自动的GPU Instancing会有很多限制,比如:不支持static batch,不支持lightmap,等等。关于Unity GPU Instancing说明以及限制。请参照官方文档https://docs.unity3d.com/Manual/GPUInstancing.html
在项目的实际应用中,我们的场景中存在大量的静态植被都需要lightmap烘焙,如果自动不支持,显然我们就要考虑手动的方式,这正是本文的目的,Unity提供了两个底层的API来进行手动的GPUInstancing,分别是Graphics.DrawMeshInstanced和Graphics.DrawMeshInstancedIndirect。
有了实现的入口,接下来就是实现的思路和流程,首先要做lightmap的支持,如果不考虑shadowmask的情况下,这个问提还是很好解决的,就是把模型对应的lightmapScaleOffset传给shader做lightmap采样,在shader走uniry 的gi流程,模型行本身不做GPUInstancing处理,考虑到混合光照的情况,还要对shadowmask进行采样,所以就需要把shadowmask贴图和光照贴图都传给shader。
这里面在项目实际操作中,遇到了两个坑:
1:如果shadowmask是多张的情况,还要通过shadowmask对对象分组,就是在一张shadowmask贴图上都有哪些对象,而最终的分组长度则会直接影响GPUInstancing的批处理数量。
2:很多项目在Quality设置选项中,都会将shadow distance的值设置的很小,这是为了保证阴影的精度。如果绘制对象过于密集,由于是按shadowmask进行分组Instancing,单张shadowmask中对象在场景中很分散,对象所对应的阴影距离超出shadow distance设置的值,表现得效果就是,不分对象没有进行shadowmask采样,这个问题在目前还没有找到很好的解决办法,有哪位小伙伴有更好解决方案可以在下面留言。
最后再通过Graphics.DrawMeshInstanced或Graphics.DrawMeshInstancedIndirect每帧绘制对象,这里还有一个问题要注意就是官方对于Graphics.DrawMeshInstanced绘制对象的个数是有限制的,最高上限上限是1023,强迫症的表示很不爽。
这是1023颗草的效果,36个DrawCall。
最后要感谢leonwei博主,起初我就看了他的文章,才有了思路,原文在这 http://blog.csdn.net/leonwei/article/details/73274808
相关文章推荐
- 对于OpenGL中光照和颜色混合的理解
- Unity5动态更新场景Lightmap,支持多张Lightmap混合
- struts2对于bigdecimal类型不支持默认转换的解决办法
- ubuntu 16.04 上安装支持GPU的caffe
- JDK1.7和JDK1.8对于异常的支持
- 高效率视频播放: GPU支持的YUV RGB 转化例子(2)
- 更新DataSet,遇到“对于不返回任何键列信息的 SelectCommand 不支持 UpdateCommand 的动态 SQL 生成
- caffe 02 win10 vs2015 编译(支持GPU)
- 对于不支持range的网络的分段下载
- 让IjkPlayer支持插入自定义的GPU滤镜
- 我以下GPU方面书籍,如果你对于GPU感兴趣的,或者需要如下书的英文复印本的请和我联系
- 高效率视频播放: GPU支持的YUV RGB 转化例子(2)
- TensorFlow(GPU支持)环境搭建
- 对于不支持cookie的浏览器,使用response.encodeURL方法来使用session
- linux kernel对于浮点运算的支持
- 移动设备对于hls协议的支持
- 对于不返回任何键列信息的 SelectCommand 不支持 UpdateCommand 的动态 SQL 生成。
- 高性能计算汇总-Mpi,openMpi,tbb,CUDA,OpenCL等并行计算或cpu,gpu混合计算技术
- 对于不返回任何键列信息的 SelectCommand 不支持 UpdateCommand 的动态 SQL 生成,异常