Eenheid Hoe maak je een shader

Shader is een klein script dat wiskundige berekeningen en algoritmen bevat voor het berekenen van de kleur van elke weergegeven pixel, op basis van de lichtinvoer en de materiaalconfiguratie.

Unity gebruikt Shaders die in de volgende talen zijn geschreven:

  • Een programmeertaal genaamd HLSL wordt gebruikt om de shader-programma's zelf te schrijven.
  • Een Unity-specifieke taal genaamd ShaderLab wordt gebruikt om een ​​Shader-object te definiëren, dat fungeert als container voor de shader-programma's.

Volg de onderstaande stappen om een ​​arcering te maken in Unity:

Maak een arcering

  • Klik met de rechtermuisknop op de projectweergave -> 'Create' -> 'Shader'

Afhankelijk van de Unity-versie die u gebruikt, kunnen de Shader-opties verschillen, maar dit is wat elk van de opties betekent:

  1. 'Standaard Surface Shader': Deze shader is ontworpen om te werken met het Unity's Physically Based Rendering (PBR) systeem. Het stelt ontwikkelaars in staat materialen te creëren die realistisch reageren op de lichtomstandigheden. Het ondersteunt verschillende weergavefuncties, zoals normale mapping, spiegelende hooglichten en reflecties. Het is een veelzijdige shader die een goede balans biedt tussen realisme en prestaties.
  2. 'Unlit Shader': Zoals de naam al doet vermoeden, houdt een onverlichte shader geen rekening met de lichtomstandigheden. Het wordt vaak gebruikt voor het renderen van effecten waarvoor geen realistische verlichting nodig is, zoals UI-elementen, deeltjessystemen of speciale effecten. Onverlichte shaders zijn doorgaans efficiënter en kunnen handig zijn in situaties waarin volledige controle over het uiterlijk van een object vereist is zonder enige verlichtingsberekeningen.
  3. 'Afbeeldingseffectshader': De afbeeldingseffect shaders worden gebruikt om nabewerking effecten toe te passen op het volledige scherm of een specifieke render doelen. Ze stellen ontwikkelaars in staat de uiteindelijk gerenderde afbeelding te wijzigen nadat de hoofdweergave is voltooid. Voorbeelden van beeldeffecten zijn vervaging, kleurcorrectie, vervorming of gestileerde filters. Ze kunnen worden gebruikt om de visuele kwaliteit te verbeteren of om specifieke artistieke effecten te creëren.
  4. 'Compute Shader': Een compute shader is een type shader dat op de GPU draait, maar niet rechtstreeks op pixels werkt. Het wordt gebruikt voor algemene berekeningen op parallelle gegevens, waardoor ontwikkelaars complexe berekeningen of simulaties efficiënt kunnen uitvoeren. Compute shaders worden vaak gebruikt voor taken zoals natuurkundige simulaties, procedurele generatie of gegevensverwerking.
  5. 'Ray Tracing Shader': Ray tracing shaders maken gebruik van ray tracing-technologie, die het gedrag van licht nauwkeuriger simuleert in vergelijking met traditionele rastertechnieken. Ray tracing shaders worden doorgaans gebruikt voor het realiseren van zeer realistische verlichting, reflecties en schaduwen in realtime toepassingen. Ze vereisen krachtige hardware en worden vaak gebruikt in grafisch-intensieve gebieden zoals gaming of architecturale visualisatie.
  • Nadat u de arcering hebt geselecteerd, typt u een naam en drukt u op Enter

De nieuwe Shader is gemaakt en kan in elke scripteditor worden geopend en aan uw behoeften worden aangepast.

Standaard '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"
}

Standaard '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
        }
    }
}

Standaard '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
        }
    }
}

Standaard '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);
}

Standaard '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);
}

Conclusie

Elk type shader heeft zijn eigen sterke punten en toepassingen. Het is belangrijk om de juiste shader te kiezen op basis van uw specifieke vereisten en de visuele effecten die u in uw project wilt bereiken.

Voorgestelde artikelen
Hoe u een Sniper Scope-effect in Unity kunt toevoegen
Een Bazooka in eenheid creëren
Een Bullet Time-effect creëren in eenheid
Kinetische interacties in eenheid implementeren
Een puzzelspel maken in eenheid
Een Pac-Man-geïnspireerd spel creëren in Unity
Hoe videobestanden in Unity af te spelen