Unity Hur man skapar en Shader

Shader är ett litet skript som innehåller matematiska beräkningar och algoritmer för att beräkna färgen på varje pixel som återges, baserat på ljusinmatningen och materialkonfigurationen.

Unity använder Shaders som är skrivna på följande språk:

  • Ett programmeringsspråk som kallas HLSL används för att skriva själva shader-programmen.
  • Ett Unity-specifikt språk som heter ShaderLab används för att definiera ett Shader-objekt, som fungerar som en behållare för shader-programmen.

Följ stegen nedan för att skapa en skuggning i Unity:

Skapa en Shader

  • Högerklicka på projektvyn -> 'Create' -> 'Shader'

Beroende på vilken version av Unity du använder kan Shader-alternativen skilja sig, men här är vad vart och ett av alternativen betyder:

  1. 'Standard Surface Shader': Denna shader är designad för att fungera med Unity's system för fysiskt baserad rendering (PBR). Det tillåter utvecklare att skapa material som reagerar på ljusförhållandena realistiskt. Den stöder olika renderingsfunktioner som normal kartläggning, spegelhöjdpunkter och reflektioner. Det är en mångsidig shader som ger en bra balans mellan realism och prestanda.
  2. 'Unlit Shader': Som namnet antyder, tar en obelyst shader inte hänsyn till ljusförhållandena. Det används ofta för att återge effekter som inte behöver realistisk belysning, som UI-element, partikelsystem eller specialeffekter. Obelysta shaders är vanligtvis mer effektiva och kan vara användbara i situationer där det kräver full kontroll över utseendet på ett objekt utan några ljusberäkningar.
  3. 'Image Effect Shader': bildeffekten-skuggningarna används för att applicera efterbehandlingseffekter på hela skärmen eller specifika renderingsmål. De tillåter utvecklare att ändra den slutliga renderade bilden efter att huvudrenderingen är klar. Exempel på bildeffekter är suddighet, färggradering, förvrängning eller stiliserade filter. De kan användas för att förbättra den visuella kvaliteten eller skapa specifika konstnärliga effekter.
  4. 'Compute Shader': En beräkningsskuggning är en typ av skuggning som körs på GPU:n men som inte fungerar på pixlar direkt. Den används för generella beräkningar på parallella data, vilket gör att utvecklare kan utföra komplexa beräkningar eller simuleringar effektivt. Compute shaders används ofta för uppgifter som fysiksimuleringar, procedurgenerering eller databehandling.
  5. 'Ray Tracing Shader': Strålspårningsskuggare använder strålspårningsteknik, som simulerar ljusets beteende mer exakt jämfört med traditionella rastertekniker. Ray tracing shaders används vanligtvis för att uppnå mycket realistisk belysning, reflektioner och skuggor i realtidsapplikationer. De kräver kraftfull hårdvara och används ofta inom grafikintensiva områden som spel eller arkitektonisk visualisering.
  • När du har valt skuggningen skriver du valfritt namn och trycker på Retur

Den nya Shader skapas och kan öppnas i valfri skriptredigerare och modifieras för att passa dina 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);
}

Slutsats

Varje shadertyp har sina egna styrkor och användningsområden. Det är viktigt att välja rätt shader baserat på dina specifika krav och de visuella effekter du strävar efter att uppnå i ditt projekt.