0

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.stack.imgur.com/qMQfE.jpg

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

Here is a picture of what editing the shader looks like currently: https://i.stack.imgur.com/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"
}
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
cyo
  • 69
  • 1
  • 14
  • is this hlsl or glsl? – Bacon Oct 10 '19 at 20:04
  • @bacon It's shaderlab, so basically hlsl – Ruzihm Oct 10 '19 at 20:05
  • The shader in the question changes the color of the surface based on where you're looking at so that no matter what direction you're looking from, the exact location of the gradient on the surface is based from where the camera is. In other words, the "center" of the gradient always faces the camera. Do you want the vertical gradient to move as you move the camera as well? – Ruzihm Oct 10 '19 at 20:57
  • It would certainly be ideal to have the gradient move with me, so that it stays consistent. – cyo Oct 10 '19 at 21:11
  • @cyo I made a mockup of a shader in shadertoy - does [this](https://www.shadertoy.com/view/3dKGRt) have the sort of appearance you want? You can hold left click to drag the camera around a little bit. – Ruzihm Oct 10 '19 at 22:36
  • This is very close to what I am looking for @Ruzihm - I suppose only thing is that the `ScanLines` (Maybe you experimented with them?) are supposed to stay as a consistent gradient as they progress up the cylinder mesh. Again, thank you so much. – cyo Oct 11 '19 at 05:01
  • @Ruzihm , In fact, I just want to emulate a simple lights (like LED's) moving up a cylinder (just as you have experimented with in Unity). So for me, all I want to achieve is patterned vertical gradients that moves up and down a mesh. I figure, white light on the bottom (Or the color of the cylinder),warm light in the middle, than white light (or the color of the cylinder), moving in xyz space. And I thought this would be simple, haha. – cyo Oct 11 '19 at 05:05

1 Answers1

0

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;

    }
}
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • 1
    Hi @ruzihm The gradient went red black red. – cyo Oct 10 '19 at 21:13
  • 1
    do you imagine is it possible to use the create a material with the shader, or will I need to always incorporate the c# script for control over the individual elements? Im building out the C# script currently to make all of the adjustable value public for greater control. This looks awesome by the way . – cyo Oct 11 '19 at 16:14
  • @cyo Oh yeah absolutely, you can just have the shader in a material (this is one of the things this answer's c# code does for you). I just put the c# code in to make a demo that's reproducible from nothing. You don't need any c# code to see the effect if you set it up in the unity editor. – Ruzihm Oct 11 '19 at 16:29
  • That what I thought would be the case, but when I right click and create a shader from the hologram.shader file it just comes out as white. I am sure there is a step I am missing – cyo Oct 11 '19 at 16:31
  • @cyo sounds good, I think this is a good place to leave this question, if you have any further question about how to modify/adapt the shader it's probably best to have it in a new post. Don't forget to mark the answer as accepted to help people see the question was solved from the search page and also give me some reputation points 8) – Ruzihm Oct 11 '19 at 16:42
  • Edited because I did not see you latest comment (Posted before seeing you want to make a new thread): So I have a funny problem now, where the model I am working with doesn't like the vectors(I assuming), Just for the sake of testing, is there a way to make the gradient go the other direction? (I am laughing because of course this would be the case -- I think it is just the model I am using...) here is a photo of how it looks attatched to the model https://imgur.com/a/GEEdwtF – cyo Oct 11 '19 at 17:20
  • @cyo this is simple, to go other direction, pulse speed parameter can be negative and if you mean "go in the other axis", change `i.uv.y` to `i.uv.x` – Ruzihm Oct 11 '19 at 17:22
  • 1
    That did it. Thank you so much for your help, I am so thankful to the people who are willing to hold your hand through the learning process of making an idea in your head come to life. – cyo Oct 11 '19 at 17:31