Unity Comment créer un shader

Shader est un petit script qui contient des calculs mathématiques et des algorithmes pour calculer la couleur de chaque pixel rendu, en fonction de l'entrée d'éclairage et de la configuration du matériau.

Unity utilise des shaders écrits dans les langages suivants:

  • Un langage de programmation appelé HLSL est utilisé pour écrire les programmes de shader eux-mêmes.
  • Un langage spécifique à Unity appelé ShaderLab est utilisé pour définir un objet Shader, qui agit comme un conteneur pour les programmes de shader.

Pour créer un shader dans Unity, suivez les étapes ci-dessous:

Créer un shader

  • Faites un clic droit sur la vue du projet -> 'Create' -> 'Shader'

Selon la version Unity que vous utilisez, les options Shader peuvent différer, mais voici ce que signifie chacune des options:

  1. 'Standard Surface Shader': Ce shader est conçu pour fonctionner avec le système Unity's de rendu physique (PBR). Il permet aux développeurs de créer des matériaux qui répondent aux conditions d'éclairage de manière réaliste. Il prend en charge diverses fonctionnalités de rendu telles que le mappage normal, les reflets spéculaires et les réflexions. C'est un shader polyvalent qui offre un bon équilibre entre réalisme et performance.
  2. 'Unlit Shader': Comme son nom l'indique, un shader non éclairé ne tient pas compte des conditions d'éclairage. Il est souvent utilisé pour rendre des effets qui ne nécessitent pas d'éclairage réaliste, tels que des éléments d'interface utilisateur, des systèmes de particules ou des effets spéciaux. Les shaders non éclairés sont généralement plus efficaces et peuvent être utiles dans les situations où cela nécessite un contrôle total sur l'apparence d'un objet sans aucun calcul d'éclairage.
  3. 'Image Effect Shader': Les shaders d'effets d'image sont utilisés pour appliquer des effets de post-traitement au l'écran entier ou des cibles de rendu spécifiques. Ils permettent aux développeurs de modifier l'image rendue finale une fois le rendu principal terminé. Des exemples d'effets d'image incluent le flou, l'étalonnage des couleurs, la distorsion ou les filtres stylisés. Ils peuvent être utilisés pour améliorer la qualité visuelle ou créer des effets artistiques spécifiques.
  4. 'Compute Shader': Un shader de calcul est un type de shader qui s'exécute sur le GPU mais n'agit pas directement sur les pixels. Il est utilisé pour des calculs à usage général sur des données parallèles, permettant aux développeurs d'effectuer efficacement des calculs ou des simulations complexes. Les shaders de calcul sont couramment utilisés pour des tâches telles que les simulations physiques, la génération procédurale ou le traitement de données.
  5. 'Ray Tracing Shader': Les shaders de lancer de rayons utilisent la technologie de lancer de rayons, qui simule le comportement de la lumière avec plus de précision par rapport aux techniques de pixellisation traditionnelles. Les shaders de lancer de rayons sont généralement utilisés pour obtenir un éclairage, des réflexions et des ombres très réalistes dans des applications en temps réel. Ils nécessitent un matériel puissant et sont souvent utilisés dans des domaines à forte intensité graphique comme les jeux ou la visualisation architecturale.
  • Après avoir sélectionné le shader, tapez n'importe quel nom et appuyez sur Entrée

Le nouveau Shader est créé et peut être ouvert dans n'importe quel éditeur de script et modifié pour répondre à vos besoins.

'Standard Surface Shader' par défaut:

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

'Unlit Shader' par défaut:

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

'Image Effect Shader' par défaut:

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

'Compute Shader' par défaut:

// 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);
}

'Ray Tracing Shader' par défaut:

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

Conclusion

Chaque type de shader a ses propres forces et utilisations. Il est important de choisir le shader approprié en fonction de vos besoins spécifiques et des effets visuels que vous souhaitez obtenir dans votre projet.

Articles suggérés
Comment lire des fichiers vidéo dans Unity
Comment ajouter un effet de lunette de sniper dans Unity
Créer un bazooka dans Unity
Créer un système d'inventaire et de fabrication d'objets dans Unity
Implémentation de minuteries dans Unity
Comment faire en sorte qu'un objet suive le curseur de la souris dans Unity
Création d'un GrabPack dans Unity inspiré de Poppy Playtime