Search code examples
c#unity-game-engineradial-gradientsskybox

How to make radial gradient skybox in Unity?


Ok, I am new to skyboxes and am having some issues trying to achieve a RADIAL gradient skybox. I have a radial gradient shader, however when I put this as the skybox the part that interpolates between the two colors is too zoomed in, meaning you cant really tell its a gradient at all.

enter image description here

I think this is because its a shader thats not meant for skyboxes. I then found a shader for a linear gradient skybox which works as a linear gradient, but I need it to be radial, like from center color outwards.

Ive looked everywhere but cant find a radial gradient SKYBOX shader. My question is - how can one turn a linear gradient shader into radial for skybox? Or how can I make my existing radial gradient work for skyboxes?

I did not write this, but this is the code for the linear gradient skybox:

Shader "Custom/Horizontal Skybox"
{
    Properties
    {
        _Color1 ("Top Color", Color) = (1, 1, 1, 0)
        _Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
        _Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
        _Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
        _Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
        _Intensity ("Intensity Amplifier", Float) = 1.0
    }

    CGINCLUDE

    #include "UnityCG.cginc"

    struct appdata
    {
        float4 position : POSITION;
        float3 texcoord : TEXCOORD0;
    };

    struct v2f
    {
        float4 position : SV_POSITION;
        float3 texcoord : TEXCOORD0;
    };

    half4 _Color1;
    half4 _Color2;
    half4 _Color3;
    half _Intensity;
    half _Exponent1;
    half _Exponent2;

    v2f vert (appdata v)
    {
        v2f o;
        o.position = mul (UNITY_MATRIX_MVP, v.position);
        o.texcoord = v.texcoord;
        return o;
    }

    half4 frag (v2f i) : COLOR
    {
        float p = normalize (i.texcoord).y;
        float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
        float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
        float p2 = 1.0f - p1 - p3;
        return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
    }

    ENDCG

    SubShader
    {
        Tags { "RenderType"="Background" "Queue"="Background" }
        Pass
        {
            ZWrite Off
            Cull Off
            Fog { Mode Off }
            CGPROGRAM
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma vertex vert
            #pragma fragment frag
            ENDCG
        }
    } 
}

Like this -

enter image description here

enter image description here


Solution

  • The shader code you provided does draw a radial gradient, only along the y axis. If you flip the axis by changing the line

    float p = normalize (i.texcoord).y;
    

    to

    float p = normalize (i.texcoord).x;
    

    Edit:

    Since you actually want to rotate the gradient, you can do the following in the vertex shader (1.57 is pi/2).

    v2f vert (appdata v)
    {
        v2f o;
        float sinX = sin ( 1.57 );
        float cosX = cos ( 1.57 );
        float sinY = sin ( 1.57 );
        float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
        o.position = mul (UNITY_MATRIX_MVP, v.position);
        o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
        o.texcoord.y = v.texcoord.y;
        return o;
    }
    

    Edit 2:

    Complete code:

    Shader "Custom/Horizontal Skybox"
    {
        Properties
        {
            _Color1 ("Top Color", Color) = (1, 1, 1, 0)
            _Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
            _Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
            _Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
            _Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
            _Intensity ("Intensity Amplifier", Float) = 1.0
            _Angle ("Angle", Float) = 0.0
        }
    
        CGINCLUDE
    
        #include "UnityCG.cginc"
    
        struct appdata
        {
            float4 position : POSITION;
            float3 texcoord : TEXCOORD0;
        };
    
        struct v2f
        {
            float4 position : SV_POSITION;
            float3 texcoord : TEXCOORD0;
        };
    
        half4 _Color1;
        half4 _Color2;
        half4 _Color3;
        half _Intensity;
        half _Exponent1;
        half _Exponent2;
        half _Angle;
    
        v2f vert (appdata v)
        {
            v2f o;
            float sinX = sin ( _Angle );
            float cosX = cos ( _Angle );
            float sinY = sin ( _Angle );
            float2x2 rotationMatrix = float2x2( cosX, -sinX, sinY, cosX);
            o.position = mul (UNITY_MATRIX_MVP, v.position);
            o.texcoord.xz = mul(v.texcoord.xz, rotationMatrix);
            o.texcoord.y = v.texcoord.y;
            return o;
        }
    
        half4 frag (v2f i) : COLOR
        {
            float p = normalize (i.texcoord).x;
            float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
            float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
            float p2 = 1.0f - p1 - p3;
            return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
        }
    
        ENDCG
    
        SubShader
        {
            Tags { "RenderType"="Background" "Queue"="Background" }
            Pass
            {
                ZWrite Off
                Cull Off
                Fog { Mode Off }
                CGPROGRAM
                #pragma fragmentoption ARB_precision_hint_fastest
                #pragma vertex vert
                #pragma fragment frag
                ENDCG
            }
        }
    }