unity-game-engineshadergradientshaderlab

Trying to modify Shader so that the colors are vertical and not horizontal


This shader (copied below) makes a material kind of like a radial gradient. I am trying to modify it to have the shader effect resemble something like a vertical/linear gradient,like this. I don't believe it is creating is a true gradient but rather adding colors and adding alpha between them. It is based off of this awesome project .

Here is picture of the effect I have currently with this shader and the scanlines effect turned on: https://i.sstatic.net/qMQfE.jpg

And here is picture of what I need the effect to look like: https://i.sstatic.net/XIoNe.jpg

Here is a picture of what editing the shader looks like currently: https://i.sstatic.net/hdzpK.jpg (This appears to be radial,no?)

I have tried modifying the direction, tried applying masks and nothing has worked so far. If anyone has any suggestions, I would be eternally thankful.

Shader "SFHologram/HologramShader"
{
    Properties
    {
        // General
        _TopColor ("Top Color", Color) = (1, 0.3, 0.3, 0)
        _BottomColor ("Bottom Color", Color) = (0.3, 0.3, 1, 0)
        _Up ("Up", Vector) = (0, 1, 0)
        _Exp ("Exp", Range(0, 16)) = 1

        _Brightness("Brightness", Range(0.1, 6.0)) = 3.0
        _Alpha ("Alpha", Range (0.0, 100)) = 1.0
        _Direction ("Direction", Vector) = (0,1,0,0)
        // Main Color
        _MainTex ("MainTexture", 2D) = "white" {}
        _MainColor ("MainColor", Color) = (1,1,1,100)
        // Rim/Fresnel
        _RimColor ("Rim Color", Color) = (1,1,1,1)
        _RimPower ("Rim Power", Range(0.1, 10)) = 5.0
        // Scanline
        _ScanTiling ("Scan Tiling", Range(0.01, 10.0)) = 0.05
        _ScanSpeed ("Scan Speed", Range(-2.0, 2.0)) = 1.0
        _ScanColor ("ScanColor", Color) = (255,1,1,1)
        // Glow
        _GlowTiling ("Glow Tiling", Range(0.01, 1.0)) = 0.05
        _GlowSpeed ("Glow Speed", Range(-10.0, 10.0)) = 1.0
        // Glitch
        _GlitchSpeed ("Glitch Speed", Range(0, 50)) = 1.0
        _GlitchIntensity ("Glitch Intensity", Float) = 0
        // Alpha Flicker
        _FlickerTex ("Flicker Control Texture", 2D) = "white" {}
        _FlickerSpeed ("Flicker Speed", Range(0.01, 100)) = 1.0

        // Settings
        [HideInInspector] _Fold("__fld", Float) = 1.0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        LOD 100
        ColorMask RGB
        Cull Back

        Pass
        {
            CGPROGRAM
            #pragma shader_feature _SCAN_ON
            #pragma shader_feature _GLOW_ON
            #pragma shader_feature _GLITCH_ON
            #pragma vertex vert
            #pragma fragment frag
            fixed3 _TopColor, _BottomColor;
            float3 _Up;
            float _Exp;

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 worldVertex : TEXCOORD1;
                float3 viewDir : TEXCOORD2;
                float3 worldNormal : NORMAL;
            fixed4 col : COLOR;
            };

            sampler2D _MainTex;
            sampler2D _FlickerTex;
            float4 _Direction;
            float4 _MainTex_ST;
            float4 _MainColor;
            float4 _ScanColor;
            float4 _RimColor;
            float _RimPower;
            float _GlitchSpeed;
            float _GlitchIntensity;
            float _Brightness;
            float _Alpha;
            float _ScanTiling;
            float _ScanSpeed;
            float _GlowTiling;
            float _GlowSpeed;
            float _FlickerSpeed;

            v2f vert (appdata v)
            {
                v2f o;

                // Glitches
                #if _GLITCH_ON
                    v.vertex.x += _GlitchIntensity * (step(0.5, sin(_Time.y * 2.0 + v.vertex.y * 1.0)) * step(0.99, sin(_Time.y*_GlitchSpeed * 0.5)));
                #endif

                o.vertex = UnityObjectToClipPos(v.vertex);

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldVertex = mul(unity_ObjectToWorld, v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.viewDir = normalize(UnityWorldSpaceViewDir(o.worldVertex.xyz));

                return o;
            }


            fixed4 frag (v2f i) : SV_Target
            {

                fixed4 texColor = tex2D(_MainTex, i.uv);
                fixed4 randomColor = (255,0,0,0);
                half dirVertex = (dot(i.worldVertex, normalize(float4(_Direction.xyz, 1.0))) + 1) / 2;



                // Glow
                float glow = 0.0;
                #ifdef _GLOW_ON
                glow = frac(dirVertex * _GlowTiling - _Time.x * _GlowSpeed);
                #endif

                // Flicker
                fixed4 flicker = tex2D(_FlickerTex, _Time * _FlickerSpeed);

                // Rim Light

                half rim = 1.0-saturate(dot(i.viewDir, i.worldNormal));
                fixed4 rimColor = _RimColor * pow (rim, _RimPower);

                fixed4 col = texColor * _MainColor + (glow * 0.35 * _MainColor) + rimColor;

                // Scanlines
                float scan = 0.0;
                #ifdef _SCAN_ON
                scan = step(frac(dirVertex * _ScanTiling + _Time.w * _ScanSpeed), 0.5) * 0.65;
                #endif


                col.a = texColor.a * _Alpha * (scan);  

                col.rgb *= _Brightness;

                return col;
            }
            ENDCG
        }
    }

    CustomEditor "HologramShaderGUI"
}

Solution

  • So, the part you want to change is the section involving rim:

    half rim = 1.0-saturate(dot(i.viewDir, i.worldNormal));
    fixed4 rimColor = _RimColor * pow (rim, _RimPower);
    

    Currently, it compares the normal of each pixel to the view direction, and the more similar they are, the less the RimColor applies.


    Here's an attempt at making this logic work but with "up" and the view direction, so that the more similar they are, the more _TopColor goes into rimColor, and the more opposite, the more _BottomColor goes into rimColor:

    Shader "SFHologram/HologramShader"
    {
        Properties
        {
            // General
            _TopColor("Top Color", Color) = (1, 0.3, 0.3, 0)
            _BottomColor("Bottom Color", Color) = (0.3, 0.3, 1, 0)
            _Up("Up", Vector) = (0, 1, 0)
            _Exp("Exp", Range(0, 16)) = 1
    
            _Brightness("Brightness", Range(0.1, 6.0)) = 1.0
            _Alpha("Alpha", Range(0.0, 100)) = 1.0
            _Direction("Direction", Vector) = (0,1,0,0)
            // Main Color
            _MainTex("MainTexture", 2D) = "white" {}
            _MainColor("MainColor", Color) = (1,1,1,100)
                // Rim/Fresnel
                _RimColor("Rim Color", Color) = (1,1,1,1)
                _RimPower("Rim Power", Range(0.1, 10)) = 5.0
                _RimGap("Rim Gap", Range(0,1)) = 0.75
                _RimChangeRate("Rim Change Rate", Range(0,5)) = 1.0
                // Scanline
                _ScanTiling("Scan Tiling", Range(0.01, 10.0)) = 0.05
                _ScanSpeed("Scan Speed", Range(-2.0, 2.0)) = 1.0
                _ScanColor("ScanColor", Color) = (255,1,1,1)
                // Glow
                _GlowTiling("Glow Tiling", Range(0.01, 1.0)) = 0.05
                _GlowSpeed("Glow Speed", Range(-10.0, 10.0)) = 1.0
                // Glitch
                _GlitchSpeed("Glitch Speed", Range(0, 50)) = 1.0
                _GlitchIntensity("Glitch Intensity", Float) = 0
                // Alpha Flicker
                _FlickerTex("Flicker Control Texture", 2D) = "white" {}
                _FlickerSpeed("Flicker Speed", Range(0.01, 100)) = 1.0
    
                    // Settings
                    [HideInInspector] _Fold("__fld", Float) = 1.0
        }
            SubShader
                {
                    Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
                    Blend SrcAlpha OneMinusSrcAlpha
                    LOD 100
                    ColorMask RGB
                    Cull Back
    
                    Pass
                    {
                        CGPROGRAM
                        #pragma shader_feature _SCAN_ON
                        #pragma shader_feature _GLOW_ON
                        #pragma shader_feature _GLITCH_ON
                        #pragma vertex vert
                        #pragma fragment frag
                        float _Exp;
    
                        #include "UnityCG.cginc"
    
                        struct appdata
                        {
                            float4 vertex : POSITION;
                            float3 normal : NORMAL;
                            float2 uv : TEXCOORD0;
                        };
    
                        struct v2f
                        {
                            float4 vertex : SV_POSITION;
                            float2 uv : TEXCOORD0;
                            float4 worldVertex : TEXCOORD1;
                            float3 viewDir : TEXCOORD2;
                            float3 worldNormal : NORMAL;
                        };
    
                        sampler2D _MainTex;
                        sampler2D _FlickerTex;
                        float4 _Direction;
                        float4 _MainTex_ST;
                        float4 _MainColor;
                        float4 _ScanColor;
                        float _RimPower;
                        float _RimGap;
                        float _RimChangeRate;
                        float _GlitchSpeed;
                        float _GlitchIntensity;
                        float _Brightness;
                        float _Alpha;
                        float _ScanTiling;
                        float _ScanSpeed;
                        float _GlowTiling;
                        float _GlowSpeed;
                        float _FlickerSpeed;
    
                        fixed4 _TopColor;
                        fixed4 _BottomColor;
    
                        v2f vert(appdata v)
                        {
                            v2f o;
    
                            // Glitches
                            #if _GLITCH_ON
                                v.vertex.x += _GlitchIntensity * (step(0.5, sin(_Time.y * 2.0 + v.vertex.y * 1.0)) * step(0.99, sin(_Time.y*_GlitchSpeed * 0.5)));
                            #endif
    
                            o.vertex = UnityObjectToClipPos(v.vertex);
    
                            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                            o.worldVertex = mul(unity_ObjectToWorld, v.vertex);
                            o.worldNormal = UnityObjectToWorldNormal(v.normal);
                            o.viewDir = normalize(WorldSpaceViewDir(v.vertex));
    
                            return o;
                        }
    
    
                        fixed4 frag(v2f i) : SV_Target
                        {
    
                            fixed4 texColor = tex2D(_MainTex, i.uv);
                            fixed4 randomColor = fixed4(255,0,0,0);
                            half dirVertex = (dot(i.worldVertex, normalize(float4(_Direction.xyz, 1.0))) + 1) / 2;
    
                            // Glow
                            float glow = 0.0;
                            #ifdef _GLOW_ON
                            glow = frac(dirVertex * _GlowTiling - _Time.x * _GlowSpeed);
                            #endif
    
                            // Flicker
                            fixed4 flicker = tex2D(_FlickerTex, _Time * _FlickerSpeed);
    
                            half rim = dot(i.viewDir, half3(0, 1, 0));
                            half topRim = saturate(smoothstep(-0.5*_RimGap, -1., rim)*_RimChangeRate);
                            half bottomRim = saturate(smoothstep( 0.5*_RimGap, 1., rim)*_RimChangeRate);
    
                            fixed4 rimColor = _TopColor * topRim +  _BottomColor * bottomRim;
    
                            fixed4 col = texColor * _MainColor + (glow * 0.35 * _MainColor) + rimColor;
    
                            // Scanlines
                            float scan = 1.0;
                            #ifdef _SCAN_ON
                            scan = step(frac(dirVertex * _ScanTiling + _Time.w * _ScanSpeed), 0.5) * 0.65;
                            #endif
    
                            col.a = texColor.a * _Alpha * (scan);
    
                            col.rgb *= _Brightness;
    
                            return col;
                        }
                        ENDCG
                    }
                }
        CustomEditor "HologramShaderGUI"
    }
    

    bottom of cylinder top of cylinder


    Second version lerps between the cylinder color and a pulse color based on time and the uv of the pixel, using a truncated sine curve:

    Shader "SFHologram/HologramShader"
    {
        Properties
        {
            // General
            _Exp("Exp", Range(0, 16)) = 1
    
            _Brightness("Brightness", Range(0.1, 6.0)) = 3.0
            _Alpha("Alpha", Range(0.0, 100)) = 1.0
            _Direction("Direction", Vector) = (0,1,0,0)
            // Main Color
            _MainTex("MainTexture", 2D) = "white" {}
            _MainColor("MainColor", Color) = (1,1,1,100)
                // Pulse
                _PulseColor("Pulse Color", Color) = (1, 0.3, 0.3, 1)
                _PulseLength("Pulse Length", Float) = 0.5
                _PulseFreq("Pulse Frequency",Float) = 20.0
                _PulseSpeed("Pulse Speed", Float) = -4.0
                _PulseGradient("Pulse Gradient", Float) = 0.8
                // Scanline
                _ScanTiling("Scan Tiling", Range(0.01, 10.0)) = 0.05
                _ScanSpeed("Scan Speed", Range(-2.0, 2.0)) = 1.0
                _ScanColor("ScanColor", Color) = (255,1,1,1)
                // Glow
                _GlowTiling("Glow Tiling", Range(0.01, 1.0)) = 0.05
                _GlowSpeed("Glow Speed", Range(-10.0, 10.0)) = 1.0
                // Glitch
                _GlitchSpeed("Glitch Speed", Range(0, 50)) = 1.0
                _GlitchIntensity("Glitch Intensity", Float) = 0
                // Alpha Flicker
                _FlickerTex("Flicker Control Texture", 2D) = "white" {}
                _FlickerSpeed("Flicker Speed", Range(0.01, 100)) = 1.0
    
                    // Settings
                    [HideInInspector] _Fold("__fld", Float) = 1.0
        }
            SubShader
                {
                    Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
                    Blend SrcAlpha OneMinusSrcAlpha
                    LOD 100
                    ColorMask RGB
                    Cull Back
    
                    Pass
                    {
                        CGPROGRAM
                        #pragma shader_feature _SCAN_ON
                        #pragma shader_feature _GLOW_ON
                        #pragma shader_feature _GLITCH_ON
                        #pragma vertex vert
                        #pragma fragment frag
                        float _Exp;
    
                        #include "UnityCG.cginc"
    
                        struct appdata
                        {
                            float4 vertex : POSITION;
                            float3 normal : NORMAL;
                            float2 uv : TEXCOORD0;
                        };
    
                        struct v2f
                        {
                            float4 vertex : SV_POSITION;
                            float2 uv : TEXCOORD0;
                            float4 worldVertex : TEXCOORD1;
                            float3 viewDir : TEXCOORD2;
                            float3 worldNormal : NORMAL;
                        };
    
                        sampler2D _MainTex;
                        sampler2D _FlickerTex;
                        float4 _Direction;
                        float4 _MainTex_ST;
                        float4 _MainColor;
                        float4 _ScanColor;
                        float4 _PulseColor;
                        float _PulseLength;
                        float _PulseFreq;
                        float _PulseSpeed;
                        float _PulseGradient;
                        float _RimChangeRate;
                        float _GlitchSpeed;
                        float _GlitchIntensity;
                        float _Brightness;
                        float _Alpha;
                        float _ScanTiling;
                        float _ScanSpeed;
                        float _GlowTiling;
                        float _GlowSpeed;
                        float _FlickerSpeed;
    
                        fixed4 _TopColor;
                        fixed4 _BottomColor;
    
                        v2f vert(appdata v)
                        {
                            v2f o;
    
                            // Glitches
                            #if _GLITCH_ON
                                v.vertex.x += _GlitchIntensity * (step(0.5, sin(_Time.y * 2.0 + v.vertex.y * 1.0)) * step(0.99, sin(_Time.y*_GlitchSpeed * 0.5)));
                            #endif
    
                            o.vertex = UnityObjectToClipPos(v.vertex);
    
                            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                            o.worldVertex = mul(unity_ObjectToWorld, v.vertex);
                            o.worldNormal = UnityObjectToWorldNormal(v.normal);
                            o.viewDir = normalize(WorldSpaceViewDir(v.vertex));
    
                            return o;
                        }
    
    
                        fixed4 frag(v2f i) : SV_Target
                        {
    
                            fixed4 texColor = tex2D(_MainTex, i.uv);
                            fixed4 randomColor = fixed4(255,0,0,0);
                            half dirVertex = (dot(i.worldVertex, normalize(float4(_Direction.xyz, 1.0))) + 1) / 2;
    
                            // Glow
                            float glow = 0.0;
                            #ifdef _GLOW_ON
                            glow = frac(dirVertex * _GlowTiling - _Time.x * _GlowSpeed);
                            #endif
    
                            // Flicker
                            fixed4 flicker = tex2D(_FlickerTex, _Time * _FlickerSpeed);
    
                            float4 col = (texColor * _MainColor + (glow * 0.35 * _MainColor));
    
                            float pulseIntensity = saturate(sin((i.uv.y / _PulseLength - _Time.x*_PulseSpeed) * _PulseFreq) * _PulseGradient);
                            col = lerp(col, _PulseColor, pulseIntensity);
    
                            // Scanlines
                            float scan = 1.0;
                            #ifdef _SCAN_ON
                            scan = step(frac(dirVertex * _ScanTiling + _Time.w * _ScanSpeed), 0.5) * 0.65;
                            #endif
    
                            col.a = texColor.a * _Alpha * (scan);
    
                            col.rgb *= _Brightness;
    
                            return col;
                        }
                        ENDCG
                    }
                }
        CustomEditor "HologramShaderGUI"
    }
    

    demo of animated pulses demo of alternate coloring

    You can test it by creating a fresh project/scene with that shader attached to the holoShader field in this script placed on the main camera, and using the scene view to navigate the scene:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class TestScript : MonoBehaviour
    {
        public Shader holoShader;
    
        private void Start()
        {
    
            Material mat = new Material(holoShader);
            mat.SetFloat("_Brightness", 1f);
            mat.SetColor("_MainColor", new Color(0.9f, 1f, 1f));
            mat.SetColor("_PulseColor", new Color(0.9f, .8f, .4f));
    
            GameObject pillar1 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            pillar1.transform.localScale = new Vector3(0.3f, 20.0f, 0.3f);
            pillar1.transform.position = new Vector3(-1f, 5f, 5f);
    
            pillar1.GetComponent<Renderer>().material = mat;
    
            GameObject pillar2 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            pillar2.transform.localScale = new Vector3(0.5f, 40.0f, 0.5f);
            pillar2.transform.position = new Vector3(2f, 13f, 8f);
    
            pillar2.GetComponent<Renderer>().material = mat;
    
        }
    }