Unity Cách tạo Shader

Shader là một tập lệnh nhỏ chứa các phép tính và thuật toán toán học để tính toán màu của từng pixel được hiển thị, dựa trên đầu vào ánh sáng và cấu hình Vật liệu.

Unity sử dụng Shaders được viết bằng các ngôn ngữ sau:

  • Một ngôn ngữ lập trình có tên HLSL được sử dụng để viết các chương trình đổ bóng.
  • Ngôn ngữ dành riêng cho Unity có tên ShaderLab được sử dụng để xác định đối tượng Shader, hoạt động như một vùng chứa cho các chương trình đổ bóng.

Để tạo trình đổ bóng trong Unity, hãy làm theo các bước bên dưới:

Tạo một Shader

  • Nhấp chuột phải vào chế độ xem Dự án -> 'Create' -> 'Shader'

Tùy thuộc vào phiên bản Unity bạn đang sử dụng, các tùy chọn Shader có thể khác nhau, nhưng đây là ý nghĩa của từng tùy chọn:

  1. 'Standard Surface Shader': Trình đổ bóng này được thiết kế để hoạt động với hệ thống Unity's Kết xuất dựa trên vật lý (PBR). Nó cho phép các nhà phát triển tạo ra các vật liệu đáp ứng điều kiện ánh sáng một cách thực tế. Nó hỗ trợ các tính năng kết xuất khác nhau như ánh xạ bình thường, điểm nổi bật và phản chiếu. Đó là một shader linh hoạt mang lại sự cân bằng tốt giữa tính chân thực và hiệu suất.
  2. 'Unlit Shader': Như tên cho thấy, trình đổ bóng không sáng sẽ không xem xét các điều kiện ánh sáng. Nó thường được sử dụng để hiển thị các hiệu ứng không cần ánh sáng thực tế, chẳng hạn như các thành phần giao diện người dùng, hệ thống hạt hoặc hiệu ứng đặc biệt. Trình đổ bóng không sáng thường hiệu quả hơn và có thể hữu ích trong các tình huống yêu cầu toàn quyền kiểm soát hình thức của vật thể mà không cần bất kỳ tính toán ánh sáng nào.
  3. 'Image Effect Shader': Bộ đổ bóng image effect được sử dụng để áp dụng các hiệu ứng xử lý hậu kỳ cho toàn bộ màn hình hoặc các mục tiêu kết xuất cụ thể. Chúng cho phép các nhà phát triển sửa đổi hình ảnh hiển thị cuối cùng sau khi quá trình hiển thị chính hoàn tất. Ví dụ về hiệu ứng hình ảnh bao gồm làm mờ, phân loại màu, biến dạng hoặc bộ lọc cách điệu. Chúng có thể được sử dụng để nâng cao chất lượng hình ảnh hoặc tạo ra các hiệu ứng nghệ thuật cụ thể.
  4. 'Compute Shader': Trình đổ bóng điện toán là một loại trình đổ bóng chạy trên GPU nhưng không hoạt động trực tiếp trên các pixel. Nó được sử dụng cho các tính toán có mục đích chung trên dữ liệu song song, cho phép các nhà phát triển thực hiện các phép tính hoặc mô phỏng phức tạp một cách hiệu quả. Trình đổ bóng điện toán thường được sử dụng cho các tác vụ như mô phỏng vật lý, tạo thủ tục hoặc xử lý dữ liệu.
  5. 'Ray Tracing Shader': Trình đổ bóng dò tia sử dụng công nghệ dò tia, mô phỏng hoạt động của ánh sáng chính xác hơn so với các kỹ thuật rasterization truyền thống. Công cụ đổ bóng dò tia thường được sử dụng để đạt được ánh sáng, phản xạ và bóng có độ chân thực cao trong các ứng dụng thời gian thực. Chúng yêu cầu phần cứng mạnh mẽ và thường được sử dụng trong các lĩnh vực chuyên sâu về đồ họa như chơi game hoặc trực quan hóa kiến ​​trúc.
  • Sau khi chọn shader, gõ tên bất kỳ và nhấn Enter

Shader mới được tạo và có thể được mở trong bất kỳ trình soạn thảo tập lệnh nào và được sửa đổi để phù hợp với nhu cầu của bạn.

Mặc định '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"
}

Mặc định '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
        }
    }
}

Mặc định '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
        }
    }
}

Mặc định '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);
}

Mặc định '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);
}

Phần kết luận

Mỗi loại shader đều có điểm mạnh và công dụng riêng. Điều quan trọng là chọn trình đổ bóng thích hợp dựa trên yêu cầu cụ thể của bạn và hiệu ứng hình ảnh mà bạn mong muốn đạt được trong dự án của mình.