1

I have a problem with a shader I made/cobbled together from bits of code

Initially my plan was to was a shader at runtime Shader on disabled object? But this seems to be the wrong thing to do, as its my understanding now that shaders can't be swapped at runtime.

So I would like to be able to correct the shader I have so that I can fade from colour to greyscale but not have part of the model disappearing. I really don't understand shaders...

The code I have so far

Shader "Custom/GreyScaleToColour"
{
Properties
{
    [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
    _Color("Tint", Color) = (1,1,1,1)
    [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
    [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
    [PerRendererData] _AlphaTex("External Alpha", 2D) = "white" {}
    [PerRendererData] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    _EffectAmount("Effect Amount", Range(0, 1)) = 1.0
    _Brightness("Brightness", Range(0, 1.5)) = 0.5
}

    SubShader
    {
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "PreviewType" = "Plane"
            "CanUseSpriteAtlas" = "True"
        }

        //Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
        #pragma multi_compile _ PIXELSNAP_ON
        #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
        #include "UnitySprites.cginc"

        struct Input
        {
            float2 uv_MainTex;
            fixed4 color;
        };

        void vert(inout appdata_full v, out Input o)
        {
            v.vertex.xy *= _Flip.xy;

            #if defined(PIXELSNAP_ON)
            v.vertex = UnityPixelSnap(v.vertex);
            #endif

            UNITY_INITIALIZE_OUTPUT(Input, o);
            o.color = v.color * _Color * _RendererColor;
        }
        uniform float _EffectAmount;
        uniform float _Brightness;

        void surf(Input IN, inout SurfaceOutput o)
        {
            fixed4 c = SampleSpriteTexture(IN.uv_MainTex) * IN.color;
            c.rgb = lerp(c.rgb, dot(c.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount);
            //o.Albedo = c.rgb * c.a;
            o.Albedo = c.rgb * _Brightness;
            //o.Albedo = (c.r + c.g + c.b) / 3 * _Brightness;
            o.Alpha = c.a;
        }
        ENDCG
    }

        Fallback "Sprite/Diffuse"
}

Part of the model disappears...

enter image description here

Strange artifacts appear

enter image description here

How it should look approximately

enter image description here

With thanks Natalie

StackBuddy
  • 577
  • 5
  • 17

1 Answers1

0

Regarding the swapping of Shaders at runtime - you don't need to swap the Shaders at runtime. You can simply enable/disable different GameObjects with the correct shaders on them.

// Assigned in the Editor
GameObject disabledGO; // Contains the Material with the Disabled Shader
GameObject normalGO; // Contains the Material with the Normal Shader

bool isDisabled = false;

private void Start()
{
    disabledGO.SetActive(isDisabled);
    normalGO.SetActive(!isDisabled);
}

private void Update()
{
    if (Input.GetKey(KeyCode.E))
    {
        isDisabled = !isDisabled;
        disabledGO.SetActive(isDisabled);
        normalGO.SetActive(!isDisabled);
    }
}
  • Hmm yes that could be one way of doing it, but I would prefure perhaps to have two materials and swap the material - at least from what I read, it might be possible to have a different shader on one of the materials, so I don't have to duplicate game objects... Im not sure if its possible to swap a shader at runtime...as Im not sure it can compile... and how costly it is if it is possible. Until I can get the shader to work though its all a mystery. :P – StackBuddy Feb 05 '20 at 15:08
  • 1
    It's not a good idea to swap Shaders at runtime, no - but the method I listed above is how nearly all games do it. For example, when you hover over units in an RTS and they highlight, that's actually the GameObject being swapped out for one with a outline Shader. Some games do it differently, but that's the main method as it's very performant. Swapping Materials is also possible, yes, but it's a little bit more convoluted and doesn't really perform better so it's (usually, not always) better to do the GameObject swapping method. – Schalk van der Merwe Feb 05 '20 at 15:12
  • Nice in that case ill give it a try - I haven't done anything for games before so its interesting to see how its tackled! thanks :) – StackBuddy Feb 05 '20 at 15:23
  • Thanks Schalk van der Merwe I've given your idea a try, that part works :) Now onto new problems! https://stackoverflow.com/questions/60082587/creating-an-unlockable-game-asset-writing-a-simple-class – StackBuddy Feb 05 '20 at 19:10
  • Send me an invite on Discord, and I'll help where I can. Chalk#7803 – Schalk van der Merwe Feb 05 '20 at 20:19
  • Thanks, Schalk! I will :) but ill get my stuff more in order before - at the moment im working on timeline animations... so once I've got some stuff to work with, the questions will arrive on implementation :P - but was pretty happy how it turned out https://www.youtube.com/watch?v=5p7NnHMW6RQ&feature=youtu.be - cheers! – StackBuddy Feb 06 '20 at 08:17