Unity Sådan opretter du en Shader

Shader er et lille script, der indeholder matematiske beregninger og algoritmer til beregning af farven på hver pixel, der gengives, baseret på lysinput og materialekonfiguration.

Unity bruger Shaders, der er skrevet på følgende sprog:

  • Et programmeringssprog kaldet HLSL bruges til at skrive selve shader-programmerne.
  • Et Unity-specifikt sprog kaldet ShaderLab bruges til at definere et Shader-objekt, som fungerer som en container for shader-programmerne.

Følg nedenstående trin for at oprette en skygge i Unity:

Opret en Shader

  • Højreklik på projektvisningen -> 'Create' -> 'Shader'

Afhængigt af den Unity version, du bruger, kan Shader-indstillingerne variere, men her er, hvad hver af mulighederne betyder:

  1. 'Standard Surface Shader': Denne shader er designet til at fungere med Unity's Physical Based Rendering (PBR) system. Det giver udviklere mulighed for at skabe materialer, der reagerer på lysforhold realistisk. Det understøtter forskellige gengivelsesfunktioner som normal kortlægning, spejlende højdepunkter og refleksioner. Det er en alsidig shader, der giver en god balance mellem realisme og ydeevne.
  2. 'Unlit Shader': Som navnet antyder, tager en uoplyst skygge ikke lysforhold i betragtning. Det bruges ofte til at gengive effekter, der ikke kræver realistisk belysning, såsom UI-elementer, partikelsystemer eller specialeffekter. Uoplyste shaders er typisk mere effektive og kan være nyttige i situationer, hvor det kræver fuld kontrol over et objekts udseende uden nogen lysberegninger.
  3. 'Image Effect Shader': billedeffekten shaders bruges til at anvende efterbehandling effekter på hele skærmen eller specifikke gengivelsesmål. De giver udviklere mulighed for at ændre det endelige renderede billede, efter at hovedgengivelsen er fuldført. Eksempler på billedeffekter omfatter sløring, farvegradering, forvrængning eller stiliserede filtre. De kan bruges til at forbedre den visuelle kvalitet eller skabe specifikke kunstneriske effekter.
  4. 'Compute Shader': En compute shader er en type shader, der kører på GPU'en, men som ikke fungerer direkte på pixels. Det bruges til generelle beregninger på parallelle data, hvilket giver udviklere mulighed for at udføre komplekse beregninger eller simuleringer effektivt. Compute shaders bruges almindeligvis til opgaver som fysiksimuleringer, proceduremæssig generering eller databehandling.
  5. 'Ray Tracing Shader': Ray tracing shaders anvender ray tracing teknologi, som simulerer lysets adfærd mere præcist sammenlignet med traditionelle rasteriseringsteknikker. Ray tracing shaders bruges typisk til at opnå yderst realistisk belysning, refleksioner og skygger i realtidsapplikationer. De kræver kraftig hardware og bruges ofte i grafikintensive områder som spil eller arkitektonisk visualisering.
  • Når du har valgt skygge, skriv et vilkårligt navn og tryk på Enter

Den nye Shader er oprettet og kan åbnes i en hvilken som helst script-editor og ændres, så den passer til dine behov.

Standard 'Standard Surface Shader':

Shader "Custom/NewSurfaceShader"
{
    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
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

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

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

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // 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)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Standard 'Unlit Shader':

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

Standard 'Image Effect Shader':

Shader "Hidden/NewImageEffectShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                // just invert the colors
                col.rgb = 1 - col.rgb;
                return col;
            }
            ENDCG
        }
    }
}

Standard 'Compute Shader':

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    // TODO: insert actual code here!

    Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}

Standard 'Ray Tracing Shader':

RWTexture2D<float4> RenderTarget;

#pragma max_recursion_depth 1

[shader("raygeneration")]
void MyRaygenShader()
{
    uint2 dispatchIdx = DispatchRaysIndex().xy;
   
    RenderTarget[dispatchIdx] = float4(dispatchIdx.x & dispatchIdx.y, (dispatchIdx.x & 15)/15.0, (dispatchIdx.y & 15)/15.0, 0.0);
}

Konklusion

Hver shader-type har sine egne styrker og anvendelser. Det er vigtigt at vælge den passende shader baseret på dine specifikke krav og de visuelle effekter, du sigter efter at opnå i dit projekt.