Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Overriding default shader matrices, but that's not possible?

Discussion in 'Shaders' started by INeatFreak, Mar 2, 2021.

  1. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    Hello. I am trying override unity_MatrixVP of standard shader with my own matrix custom_MatrixVP that I pass it to the shader. To do this I need to edit only a part of the standard shader, that is "UnityShaderVariables.cginc" include file where all the matrices and other camera, lighting, time related stuff declared.

    But I've realized an bug? feature? where unity doesn't allow this include file to be NOT INCLUDED. When I create my own version of this exact include file while preventing unitys, It gives the redefinition of "_Time" error.

    By looking at the file we can see that there's a #define that prevents from including multiple times:
    Code (CSharp):
    1. #ifndef UNITY_SHADER_VARIABLES_INCLUDED
    2. #define UNITY_SHADER_VARIABLES_INCLUDED
    3. // _Time, unity_MatrixVP, unity_FogColor ... etc declared here
    4. #endif
    Which means if we set #define UNITY_SHADER_VARIABLES_INCLUDED before the file is imported then the file should not be included but ohh NOO. Unity should just lie to me. EVERYTIME.

    Just use Surface Shader you might say but these don't allow users to choose transparency from editor. Have to add it by code. This should be an asset store project so I want it to be easier for users.

    Also tried deleting all the #include's on the shader and tried to use _Time, unity_MatrixVP or any other property declared on that file and it DOESN'T give me an error as it should. Which means the file is still included.

    I can't just rewrite standard shader with all the vert & frag programs just to change single line. Which is changing clip space calculation using unity_MatrixVP to custom_MatrixVP.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    Unity always includes UnityShaderVariables.cginc and a few other cginc files at the start of every shader even if you have no
    #pragma include
    lines. There's no way to inject code before that to prevent those from being added to the shader.
     
  3. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    Well that sucks. Can I know what are other cginc files that is included automatically? There's no documentation about this.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    From what I can see (using Unity 2020's Preprocessed shader preview)
    HLSLSupport.cginc
    UnityShaderVariables.cginc
    UnityShaderUtilities.cginc
     
    INeatFreak likes this.
  5. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    Hmm. I can't use material.SetMatrix("unity_MatrixVP") nor change Camera.projectionMatrix for single object. I don't like the Unity today.

    There's also a way to rendering mesh from script with GL.LoadProjectionMatrix(projectionMatrix) and drawing with Graphics.MeshRenderNow() but that doesn't calculate lighting. Is there a way I can apply matrix to Graphics.DrawMesh? Or any other way to render with custom projection matrix without using a second camera?
     
  6. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    Or is there callbacks for before and after mesh is rendered so I can change and set back the camera matrix?

    There's MonoBehaviour.OnRenderObject callback but the documentation says "You should only use this function to draw and not to change any high level rendering states."
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    INeatFreak likes this.
  8. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    Just read this thread and it looks like rendering with command buffers has it's own limitations such as weird lighting and no shadows. Yet another dead end.
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,238
    There are some examples of rendering first person weapons with a different FOV / matrix that are probably applicable here. The TLDR version is they use a custom shader with a custom view projection matrix variable. I think that might be your best option here.

    However I think using DrawRenderer instead of DrawMesh makes it work with lighting.* Though you will need to inject your mesh into the camera depth texture and shadow maps yourself if you need them to cast / receive shadows, which is easier said than done if you're looking to use a custom projection matrix.
     
  10. INeatFreak

    INeatFreak

    Joined:
    Sep 12, 2018
    Posts:
    46
    UPDATE:
    So turns out this is only true for CGPROGRAM shaders. If you changed it to HLSLPROGRAM unity no longer includes these files.

    Another solution is applying MaterialPropertyBlock to MeshRenderers with set unity_MatrixVP property. This overrides unity's properties and doesn't give any warnings/errors. (Unfortunately this will override properties for all passes including ShadowCaster passes. Which is not desirable if mesh needs to cast shadows)
     
    bgolus likes this.