【光照】UnityURP[光照贴图]GPU instancing在静态动态物体上的应用

【从UnityURP开始探索游戏渲染】专栏-直达

静态物体GPU Instancing与光照贴图

技术要点‌:

  • 静态标记 ‌:物体需标记为Batching Static,但需禁用静态合批以避免与GPU Instancing冲突。
  • 光照贴图绑定 ‌:通过LightmapIndexLightmapScaleOffset手动绑定烘焙结果。
  • Shader适配‌:需在着色器中添加实例化支持与光照贴图采样逻辑。

示例代码‌:

  • StaticInstancingExample.cs

    csharp 复制代码
    using UnityEngine;
    
    [ExecuteAlways]
    public class StaticInstancingExample : MonoBehaviour {
        public Mesh mesh;
        public Material material;
        public int instanceCount = 100;
        private Matrix4x4[] matrices;
        private Vector4[] lightmapOffsets;
    
        void Start() {
            // 生成实例变换矩阵
            matrices = new Matrix4x4[instanceCount];
            lightmapOffsets = new Vector4[instanceCount];
            for (int i = 0; i < instanceCount; i++) {
                Vector3 pos = Random.insideUnitSphere * 10f;
                matrices[i] = Matrix4x4.TRS(pos, Quaternion.identity, Vector3.one);
    
                // 模拟不同光照贴图偏移(需与烘焙数据匹配)
                lightmapOffsets[i] = new Vector4(1, 1, i % 2 * 0.5f, i / 2 * 0.5f);
            }
        }
    
        void Update() {
            MaterialPropertyBlock props = new MaterialPropertyBlock();
            props.SetVectorArray("_LightmapST", lightmapOffsets); // 传递光照贴图UV偏移
            Graphics.DrawMeshInstanced(mesh, 0, material, matrices, instanceCount, props);
        }
    }

实现说明‌:

  • 使用MaterialPropertyBlock传递每实例的光照贴图UV偏移参数。
  • 着色器中需声明UNITY_LIGHTMAP_ON宏并采样unity_Lightmap纹理。

动态物体GPU Instancing与光照探针

技术要点‌:

  • 光照探针替代 ‌:动态物体依赖Light Probes获取间接光照。
  • 混合光源支持 ‌:光源设为Mixed模式,静态阴影烘焙到光照贴图,动态物体接收实时阴影。
  • 实例化属性扩展 ‌:通过MaterialPropertyBlock传递探针数据。

示例代码‌:

  • DynamicInstancingExample.cs

    csharp 复制代码
    using UnityEngine;
    
    public class DynamicInstancingExample : MonoBehaviour {
        public Mesh mesh;
        public Material material;
        public int instanceCount = 100;
        private Matrix4x4[] matrices;
    
        void Start() {
            matrices = new Matrix4x4[instanceCount];
            for (int i = 0; i < instanceCount; i++) {
                Vector3 pos = Random.insideUnitSphere * 10f;
                matrices[i] = Matrix4x4.TRS(pos, Quaternion.identity, Vector3.one);
            }
        }
    
        void Update() {
            MaterialPropertyBlock props = new MaterialPropertyBlock();
    
            // 为每个实例设置光照探针数据
            LightProbes.GetInterpolatedProbe(transform.position, null, out var probe);
            props.AddVector("_LightProbeData", new Vector4(probe.occlusion, 0, 0, 0));
    
            Graphics.DrawMeshInstanced(mesh, 0, material, matrices, instanceCount, props);
        }
    }

实现说明‌:

  • 通过LightProbes.GetInterpolatedProbe获取动态物体的光照探针数据。
  • 着色器中需使用SHADERGRAPH_BAKED_LIGHT_PROBES宏处理探针数据。

Shader适配关键代码(URP Shader Graph)

  • 静态光照贴图采样 ‌:在Shader Graph中添加Lightmap节点,并通过Custom Function节点接入实例化的UV偏移参数。
  • 动态探针支持 ‌:添加Baked Light Probes节点,并与实例化属性_LightProbeData关联。

优先级注意 ‌:若同时启用SRP Batcher,需确保材质兼容性(禁用MaterialPropertyBlock


【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)