首页 > Unity3D频道 > 【Unity3D研究院之游戏开发】 > Unity3D研究院之Lightmap支持GPU Instancing(一百零七)
2019
08-23

Unity3D研究院之Lightmap支持GPU Instancing(一百零七)

Unity2017是明确不支持GPU Instancing的,如果在材质上勾选了enable GPU Instancing后,如下图所示,在Frame Debugger中,我们能清楚的看到所有的游戏对象没有合批,提示Objects are lightmapped。

Unity3D研究院之Lightmap支持GPU Instancing(一百零七) - 雨松MOMO程序研究院 - 1

所以为了让Unity2017支持GPU Instancing我们就不能使用游戏对象的模式,必须采用Graphics.DrawMeshInstanced接口来绘制。具体使用方法可以看我之前的文章Unity3D研究院GPU Instancing实战(九十七)

并且参与烘焙的材质我们需要手动修改,不能使用默认的standard着色器,原因就是我们要把每个物体烘焙过的LightmapScaleOffset传进去。如果你对LightmapIndex、LightmapScaleOffset、UV2之间的关系还不太了解,可以看我之前的文章。Unity3D研究院之LightmapIndex、LightmapScaleOffset、UV2的关系(一百零六)

首先需要改造standard着色器,在ps结构体里声明float2 uv1 : TEXCOORD1。

接着需要在vs里返回和LightmapScaleOffset计算后的uv2,也就是上面定义的float2 uv1 : TEXCOORD1。

最后在PS里就可以采样lightmap的颜色了。

以上代码修改完毕,我们就可以开始烘焙场景了,如下图所示,右侧我们能看到现在还游戏对象模式。

Unity3D研究院之Lightmap支持GPU Instancing(一百零七) - 雨松MOMO程序研究院 - 2

接着我们要使用Graphics.DrawMeshInstanced来进行绘制,按照上面我们修改的shader其实只需要将unity_LightmapST传入即可,但是很遗憾的说我们不能直接传入。如下图所示,首先指定Custom材质,然后在指定一张特定的烘焙贴图,因为实际环境中可能会有多张烘焙贴图的情况。

Unity3D研究院之Lightmap支持GPU Instancing(一百零七) - 雨松MOMO程序研究院 - 3

Custom.shader,请大家注意//—add—中的内容。

最后就是Custom.cs

运行游戏,如下图所示,游戏对象都已经全部隐藏,通过Graphics.DrawMeshInstanced 一次绘制完毕,并且设置了正确的烘焙贴图。

Unity3D研究院之Lightmap支持GPU Instancing(一百零七) - 雨松MOMO程序研究院 - 4

OK,我们在来看看Unity2018和Unity2019,从Unity2018开始Lightmap已经支持GPUInstancing了,如果是游戏对象的方式烘焙完场景就直接显示lightmap了,但是为了极致的性能优化,Graphics.DrawMeshInstanced 的效率明显还是要高。

——————-以下方法在真机上不行但是编辑器上可行,所以目前来看只能用上面的方法//——————-

在Unity2019中我们打开了LWRP了,此时在去修改Shader就太麻烦了,不过还好我们可以直接传入unity_LightmapST,这样就不需要改代码了。

如下图所示,在Unity2019中lightmap已经渲染出来了。

Unity3D研究院之Lightmap支持GPU Instancing(一百零七) - 雨松MOMO程序研究院 - 5

如果Unity2019没有用LWRP,unity会计算球谐光照,需要改下代码。主要是LightProbeUsage.CustomProvided,因为CustomProvider没有提供球谐,所以这样球谐就都没有值了,所以计算就对了。

总之现在项目都在用LWRP了,用上面的方法肯定就没错了。

最后在补充一下,SRP提供了SRPBatcher,它可以对不同Mesh相同材质进行“合并”,你也可以理解合批批次,它比GPUInstancing还要好,因为后者需要同时满足相同Mesh相同材质才能合批。

如果游戏对象情况下勾选了enable GPU insatncing会优先启动SRPBatcher。

非游戏对象情况,Graphics.DrawMeshInstanced绘制出来的,才会优先启用GPUInstancing。

还有ECS提供了无游戏对象的渲染,其实也存在Lightmap的问题,按照上面的做法也同样可以显示正确的Lightmap ,还有Hybird也是同样的套路。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之Lightmap支持GPU Instancing(一百零七)》有 11 条评论

  1. gltfxe 说:

    使用不同光照贴图的对象,是不能使用Graphics.DrawMeshInstanced渲染的吗

  2. alex 说:

    block.SetTexture(“unity_Lightmap”, lightmapTexture); 中的lightmapTexture 怎么赋值

  3. 沈杰 说:

    用了custom的shader 材质球直接黑了 是哪里有问题吗

  4. 搬砖战士 说:

    materiall.EnableKeyword(“SHADOWS_SHADOWMASK”);

    block.SetTexture(“unity_ShadowMask”, LightmapSettings.lightmaps[renderer.lightmapIndex].shadowMask);
    如果需要烘焙阴影的话,建议加上这两句

  5. seven 说:

    material打ab包的情况下,使用Graphics.DrawMeshInstanced无法渲染,请问有遇到过这样的问题吗?

  6. kaikai 说:

    bake完后lightmapScaleOffset数据会被自动写入么

留下一个回复

你的email不会被公开。