Search Unity

Image effect: Why is my public shader variable automatically assigned in the inspector?

Discussion in 'Shaders' started by TwiiK, Jul 25, 2015.

  1. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    I'm fiddling about with image effects in the hopes that I can make a brightness/gamma image effect. The grayscale image effect seemed like the simplest image effect so I duplicated and renamed it. But when I apply my new image effect to the camera it is automatically assigned the wrong shader. I have no idea where Unity gets this connection from. Normally you have to manually assign public variables. How and why does Unity automatically assign this one?

    I've tried reimporting all my assets and renaming the scripts to try and break the connection, but it makes no difference. The only thing that works is to rename the variable from "shader" to something else. Then when I add the script to my camera the shader slot is empty. But why does it automatically assign it if it's called "shader" and why does it automatically assign the wrong (old) shader in the slot? I see no references between these two.

    I even looked in UnityCG.cginc to see if there was anything there, but I found nothing. I don't get it. :p

    Here's my script. It's just a clone of the grayscale script, but I've tried to remove everything I thought could cause this behavior. Things like using statements, namespaces etc.
    Code (csharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. public class Gamma : MonoBehaviour {
    5.  
    6.     public Shader shader;
    7.     Material m_Material;
    8.  
    9.     Material material {
    10.         get {
    11.             if (m_Material == null) {
    12.                 m_Material = new Material(shader);
    13.                 m_Material.hideFlags = HideFlags.HideAndDontSave;
    14.             }
    15.             return m_Material;
    16.         }
    17.     }
    18.  
    19.     void OnRenderImage(RenderTexture source, RenderTexture destination) {
    20.         Graphics.Blit(source, destination, material);
    21.     }
    22. }
    And here's my shader. It's just a straight clone of the grayscale shader, renamed.
    Code (csharp):
    1. Shader "Hidden/Gamma Effect" {
    2. Properties {
    3.     _MainTex ("Base (RGB)", 2D) = "white" {}
    4.     _RampTex ("Base (RGB)", 2D) = "grayscaleRamp" {}
    5. }
    6.  
    7. SubShader {
    8.     Pass {
    9.         ZTest Always Cull Off ZWrite Off
    10.              
    11. CGPROGRAM
    12. #pragma vertex vert_img
    13. #pragma fragment frag
    14. #include "UnityCG.cginc"
    15.  
    16. uniform sampler2D _MainTex;
    17. uniform sampler2D _RampTex;
    18. uniform half _RampOffset;
    19.  
    20. fixed4 frag (v2f_img i) : SV_Target
    21. {
    22.     fixed4 original = tex2D(_MainTex, i.uv);
    23.     fixed grayscale = Luminance(original.rgb);
    24.     half2 remap = half2 (grayscale + _RampOffset, .5);
    25.     fixed4 output = tex2D(_RampTex, remap);
    26.     output.a = original.a;
    27.     return output;
    28. }
    29. ENDCG
    30.  
    31.     }
    32. }
    33.  
    34. Fallback off
    35.  
    36. }
     
  2. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    Just find the .cs file in the "Project" tab, and click on it. On the right you should see some of the code, and above that you will see some default assignments for the public variables. You can change them there.

    They're stored in the file metadata. If you open "Grayscale.cs.meta", you will find a line:
    Code (csharp):
    1.  
    2.   defaultReferences:
    3.   - shader: {fileID: 4800000, guid: daf9781cad112c75d0008dfa8d76c639, type: 3}
    4.  
    That tells Unity to automatically assign a specific shader to the "shader" variable. If you open the grayscale shader file metadata, it should have the guid value of "daf9781cad112c75d0008dfa8d76c639". Or whatever value your Unity project decided to give it.

    Hopefully, that should solve the mystery. :)
     
    TwiiK likes this.
  3. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    Thank you! :)

    I expected it was some sort of metadata, but I thought reimporting assets would fix things like that? I just tried deleting my Library folder, showing hidden files in Windows and manually deleting the metadata file for this script file, but it still gets assigned to the Grayscale shader. Spooky.

    But now I at least know how to fix it. I guess this is a problem you only ever encounter when duplicating existing files like I did anyway.
     
  4. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    Ha ha, yeah, I would have expected deleting the metadata file to fix it although I suppose Unity may cache it somewhere and restore it if it imports a file it's seen before. I did a quick test and it restores the metadata when I delete it too.

    My guess is it must be a robustness feature to prevent your project from being destroyed if you somehow lose (or delete) all your metadata files. Probably enough people complained about their projects collapsing that they implemented an automatic metadata backup system. Usually useful, but potentially frustrating if you don't know it's there.