Javin Yang
Javin Yang

Reputation: 305

Can I use unity unitycg.cginc in compute shader?

Is it possible to use compute shader to use variable and function such as UNITY_MATRIX_MVP in #include "UnityCG.cginc" The following code will return 0 And report an error:

CG:

// Each #kernel tells which function to compile; you can have many kernels
 #pragma kernel CSMain
 #include "UnityCG.cginc"
     
 RWStructuredBuffer<float> Result;
     
 [numthreads(1,1,1)]
  void CSMain (uint3 id : SV_DispatchThreadID)
 {
     Result[id.x] = UNITY_MATRIX_MVP[0][0];
 }

C#

...
     public ComputeShader _ComputeShader;
 
     void Start()
     {
         kernelIndex = _ComputeShader.FindKernel("CSMain");
         _Result = new ComputeBuffer(1, 4);
         _ComputeShader.SetBuffer(kernelIndex, "Result", _Result);
         _ComputeShader.Dispatch(kernelIndex, 1, 1, 1);
         float[] total = new float[1];
         _Result.GetData(total);
         Debug.Log(total[0]);
     }
...

Error: Shader error in 'NewComputeShader.compute': All kernels must use same constant buffer layouts; 'unity_LightColor0' property found to be different Can I use UnityCG.cginc in compute shader? Version: Unity 2019.4.23f1c1

Upvotes: 2

Views: 685

Answers (1)

Neil Z. Shao
Neil Z. Shao

Reputation: 752

I found a workaround for this problem: calculating MVP in C# script and set it to compute shader.

void OnRenderObject()
{
    // UNITY_MATRIX_MVP
    Camera cam = Camera.current;
    //Matrix4x4 p = cam.projectionMatrix;
    Matrix4x4 p = GL.GetGPUProjectionMatrix(cam.projectionMatrix, true);
    Matrix4x4 v = cam.worldToCameraMatrix;
    Matrix4x4 m = gameObject.transform.localToWorldMatrix;
    Matrix4x4 MVP = p * v * m;
    shaderPreprocess.SetMatrix("_UNITY_MATRIX_MVP", MVP);
}

Something to note:

  • Camera.current points to current viewing camera, switching between Editor's camera and Camera.main.
  • Camera.current in stable in OnRenderObject() so I put the code here. Not stable in Update(). If you don't care about Editor's preview, you can use Camera.main and put the code in Update() maybe.
  • The true in GL.GetGPUProjectionMatrix(cam.projectionMatrix, true) leads to a flip on Y-axis.
  • In your compute shader, the variable is float4x4 _UNITY_MATRIX_MVP;

Upvotes: 0

Related Questions