Week 9 Shader Explorations

hedgehog_on_a_pedestal3_resizehedgehog_on_a_pedestal_pp2_resize

This week I decided to create some fun materials for a hedgehog model I created in Blender, by porting and building off a couple of my Week 1 shaders.  I knew from the start that I wanted to attempt the bonus prompt for this week, displacing vertices, and it ended up being perfect for procedurally generating the spikes of the quills. In the future, it would be interesting to explore how I could also animate movement in quills (i.e make them bristle or lay flat along the hedgehog’s back). For the fur and body of the Hedgehog, I  ported my rainbow wave shader from week one into a surface shader and added parameters for different textures: metallic, smoothness, emission, height, normal, and ambient occlusion. To create a fur-like effect I used a stylized grass texture set (with normals, height, roughness, etc). I used the same shader but with different texture sets or fewer textures (i.e the pedestal used the gravel (?) textures from class) for other models in the scene as well.

The post-processing shader is a simple colour threshold shader that you can control through a script.

For the stone pedestal, bottom sphere, and hedgehog fur.


Shader "Custom/HSBHSVColourBoxBlend_AnimDisplace"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
        _DispAmount("Extrusion Amount", Range(0,1)) = 0.1
        _Amplitude("Amplitude", float) = 1.0
        _AnimSpeed("Displacement Animation Speed", float) = 0.2

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue" = "Geometry"}
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows vertex:vert

        //#pragma fragment frag

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        float3 hsb2rgb(in float3 c) {
            float3 rgb = clamp(abs(fmod(c.x * 6.0 + float3(0.0, 4.0, 2.0),
                6.0) - 3.0) - 1.0,
                0.0,
                1.0);
            rgb = rgb * rgb * (3.0 - 2.0 * rgb);
            return c.z * lerp(float3(1.0, 1.0, 1.0), rgb, c.y);
        }

        struct Input
        {
            float2 uv_MainTex;
            float4 screenPos;
            float3 worldPos;

        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        float _DispAmount;
        float _Amplitude;
        float _AnimSpeed;

        void vert(inout appdata_full v) {
            v.vertex.y += sin(_Time.y * _AnimSpeed + v.vertex.y * _Amplitude) * v.normal * _DispAmount;
        }

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            //float2 st = float2(0.5, 0.5);

            float2 st = IN.worldPos.xy / IN.screenPos.w;
            //float2 st = IN.screenPos.xy / IN.screenPos.w;

            st.x = frac(st.x)*2.0;
            st.y = frac(st.y) * 20.0;

            float3 color1 = hsb2rgb(float3(sin(_Time.y) * 0.1 + st.y * 0.9, 10.0, 2.588));
            float3 color2 = color1 * 1.5 - hsb2rgb(float3(cos(_Time.y) * -0.15 + st.x * 0.7, st.x, 1.8)) * color1;

            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * float4(color2.x, color2.y, color2.z, 1.0);
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}


For the Quills.

Shader "Custom/HSBHSVColourBoxBlend_TexDisplace"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
        _DispAmount("Displacement Amount", Range(0,0.1)) = 0.01
        _DispTex("Displacement Text", 2D) = "white" {}
        _Distance("Distance", Range(-0.1,0.1)) = 0.0
        _PatternTiling("Pattern Tiling", Vector) = (2.0, 20.0, 0.0, 0.0)
    }
        SubShader
        {
            Tags { "RenderType" = "Opaque" "Queue" = "Geometry"}
            LOD 200

            CGPROGRAM
            // Physically based Standard lighting model, and enable shadows on all light types
            #pragma surface surf Standard fullforwardshadows vertex:vert

            //#pragma fragment frag

            // Use shader model 3.0 target, to get nicer looking lighting
            #pragma target 3.0

            sampler2D _MainTex;
            sampler2D _DispTex;

            float3 hsb2rgb(in float3 c) {
                float3 rgb = clamp(abs(fmod(c.x * 6.0 + float3(0.0, 4.0, 2.0),
                    6.0) - 3.0) - 1.0,
                    0.0,
                    1.0);
                rgb = rgb * rgb * (3.0 - 2.0 * rgb);
                return c.z * lerp(float3(1.0, 1.0, 1.0), rgb, c.y);
            }

            struct Input
            {
                float2 uv_MainTex;
                float2 uv_DispTex;


                float4 screenPos;
                float3 worldPos;

            };

            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
            float _DispAmount;
            float _Distance;
            float2 _PatternTiling;

            void vert(inout appdata_full v) {

                float3 color = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).rgb;

                float brightness = color.r * 0.7 + color.g * 0.2 + color.b * 0.1;

                // Calculate amount of displacement based on brightness
                float textDisp = brightness;
                textDisp -= 0.5;
                textDisp *= 0.5;

                v.vertex.xyz += v.normal * _DispAmount * textDisp;
                v.vertex.yz += _Distance;

            }

            // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
            // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
            // #pragma instancing_options assumeuniformscaling
            UNITY_INSTANCING_BUFFER_START(Props)
                // put more per-instance properties here
            UNITY_INSTANCING_BUFFER_END(Props)

            void surf(Input IN, inout SurfaceOutputStandard o)
            {
                //float2 st = float2(0.5, 0.5);

                //float2 st = IN.worldPos.xy / IN.worldPos.z;            
                float2 st = IN.worldPos.xy / IN.screenPos.w;
                //float2 st = IN.screenPos.xy / IN.screenPos.w;

                st.x = frac(st.x) * _PatternTiling.x;
                st.y = frac(st.y) * _PatternTiling.y;

                float3 color1 = hsb2rgb(float3(sin(_Time.y) * 0.1 + st.y * 0.9, 10.0, 2.588));
                float3 color2 = color1 * 1.5 - hsb2rgb(float3(cos(_Time.y) * -0.15 + st.x * 0.7, st.x, 1.8)) * color1;

                // Albedo comes from a texture tinted by color
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * float4(color2.x, color2.y, color2.z, 1.0);
                o.Albedo = c.rgb;
                // Metallic and smoothness come from slider variables
                o.Metallic = _Metallic;
                o.Smoothness = _Glossiness;
                o.Alpha = c.a;
            }
            ENDCG
        }
            FallBack "Diffuse"
}

I would add my post-processing shader but the post is already really long…

Leave a Reply