Unity计算着色器中能否使用UnityCG.cginc及UNITY_MATRIX_MVP等内置变量
问题结论与修复方案
可行性说明
Compute Shader支持引入UnityCG.cginc,但存在两个限制:
UnityCG.cginc中包含大量和内置渲染管线绑定的全局变量、常量缓冲区定义,直接引入极易触发常量缓冲区布局冲突的编译错误UNITY_MATRIX_MVP、_WorldSpaceLightPos0这类内置变量的赋值逻辑是Unity为普通顶点/片元着色器的渲染流程自动注入的,Compute Shader没有对应的上下文,不会自动填充这类变量的值,哪怕引入头文件读到的也是默认的空值。
报错原因说明
你遇到的All kernels must use same constant buffer layouts; 'unity_LightColor0' property found to be different报错,是因为UnityCG.cginc引入的灯光相关全局常量缓冲区,和Unity Compute Shader的多内核编译规则冲突:Unity要求同一个Compute Shader下的所有内核使用的常量缓冲区结构完全一致,引入UnityCG.cginc后内置变量的自动注入逻辑会破坏这个一致性,哪怕你只有一个内核也可能触发该报错。
修复方案
方案1:仅需使用UnityCG中的通用工具函数(无渲染相关内置变量需求)
不要引入全量UnityCG.cginc,选择更轻量化的头文件:
// 仅引入数学工具函数,无全局变量定义,无冲突 #include "UnityMath.cginc"
如果必须引入全量UnityCG.cginc,可在引入前添加宏定义关闭全局变量的注入,2019.4版本兼容该写法:
#define UNITY_PASS_CUSTOM #define UNITY_SKIP_GLOBAL_VARIABLES #include "UnityCG.cginc"
方案2:需要使用UNITY_MATRIX_MVP这类渲染相关矩阵变量
不要依赖Unity的自动赋值,手动从C#侧传递对应参数,改动如下:
- Compute Shader代码修改:
#pragma kernel CSMain RWStructuredBuffer<float> Result; // 自行定义需要的矩阵变量,不需要引入UnityCG float4x4 UNITY_MATRIX_MVP; [numthreads(1,1,1)] void CSMain (uint3 id : SV_DispatchThreadID) { Result[id.x] = UNITY_MATRIX_MVP[0][0]; }
- C#代码修改:
public ComputeShader _ComputeShader; // 自行指定要计算MVP矩阵的对应物体与相机 public Transform targetObject; public Camera renderCamera; void Start() { int kernelIndex = _ComputeShader.FindKernel("CSMain"); ComputeBuffer _Result = new ComputeBuffer(1, sizeof(float)); // 手动计算MVP矩阵 Matrix4x4 mvpMatrix = renderCamera.projectionMatrix * renderCamera.worldToCameraMatrix * targetObject.localToWorldMatrix; // 将矩阵传递给Compute Shader _ComputeShader.SetMatrix("UNITY_MATRIX_MVP", mvpMatrix); _ComputeShader.SetBuffer(kernelIndex, "Result", _Result); _ComputeShader.Dispatch(kernelIndex, 1, 1, 1); float[] res = new float[1]; _Result.GetData(res); Debug.Log(res[0]); // 必须释放ComputeBuffer避免内存泄漏 _Result.Release(); }
内容的提问来源于stack exchange,提问作者Javin Yang
相关产品推荐
相关产品推荐

