ShaderLab 关键点记录

ShaderLab 是 Unity 中用于编写着色器的语言。着色器是运行在 GPU 上的程序,负责处理渲染流水线中的各种图形计算。理解 ShaderLab 的关键概念和技术细节,对于开发高效、复杂的图形效果至关重要。本文将详细记录 ShaderLab 的关键点,帮助开发者深入掌握这门语言。

ShaderLab 基础

1. ShaderLab 结构

一个 ShaderLab 文件通常由以下几个部分组成:

  • Shader 名称:定义着色器的名称。
  • Properties:定义着色器可调节的属性。
  • SubShader:定义具体的渲染过程。
  • Pass:定义一个渲染通道。

示例结构:

Shader "Custom/MyShader" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color", Color) = (1,1,1,1)
    }
    SubShader {
        Pass {
            // Shader code here
        }
    }
    FallBack "Diffuse"
}

2. Properties

Properties 用于在 Inspector 窗口中暴露变量,方便调节。常见类型包括:

  • Color:颜色。
  • Vector:向量。
  • Range:范围值。
  • Float:浮点数。
  • 2D:2D 纹理。

示例:

Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Texture", 2D) = "white" {}
    _Shininess ("Shininess", Range(0.03, 1)) = 0.078125
}

3. SubShader 和 Pass

SubShader 包含一个或多个 Pass,每个 Pass 代表一个渲染步骤。

  • SubShader:用于定义多种渲染路径,以适应不同的硬件。
  • Pass:包含具体的渲染指令。

示例:

SubShader {
    Tags { "RenderType"="Opaque" }
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        // Vertex and fragment shader code
        ENDCG
    }
}

CG/HLSL 代码

ShaderLab 中嵌入的 CG 或 HLSL 代码用于编写具体的顶点和片段着色器。

1. 顶点着色器

顶点着色器负责处理顶点属性,如位置、法线等。

示例:

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : SV_POSITION;
    float3 normal : TEXCOORD0;
};

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

2. 片段着色器

片段着色器负责计算每个像素的颜色。

示例:

float4 frag (v2f i) : SV_Target {
    return float4(i.normal, 1.0);
}

常用指令和技巧

1. #pragma 指令

用于控制编译器行为,如定义顶点和片段着色器入口。

  • #pragma vertex vert:定义顶点着色器入口。
  • #pragma fragment frag:定义片段着色器入口。

2. 内置变量

Unity 提供了一些内置变量,方便在着色器中使用。

  • UNITY_MATRIX_MVP:模型视图投影矩阵。
  • unity_ObjectToWorld:对象到世界坐标的变换矩阵。

3. 纹理采样

使用 tex2D 函数进行纹理采样。

示例:

sampler2D _MainTex;
float4 frag (v2f i) : SV_Target {
    float4 texColor = tex2D(_MainTex, i.uv);
    return texColor;
}

4. 多通道渲染

使用多个 Pass 进行复杂的多通道渲染。

示例:

SubShader {
    Pass {
        // First pass
    }
    Pass {
        // Second pass
    }
}

实用例子:Phong 着色器

一个简单的 Phong 着色器示例,展示了基本的光照计算。

Shader "Custom/PhongShader" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color", Color) = (1,1,1,1)
        _Shininess ("Shininess", Range(0.03, 1)) = 0.078125
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

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

            struct v2f {
                float4 pos : SV_POSITION;
                float3 normal : TEXCOORD0;
                float2 uv : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _Color;
            float _Shininess;

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

            float4 frag (v2f i) : SV_Target {
                float3 normal = normalize(i.normal);
                float3 lightDir = normalize(float3(0.0, 0.0, 1.0));
                float3 viewDir = normalize(float3(0.0, 0.0, 1.0));

                // Diffuse
                float diff = max(dot(normal, lightDir), 0.0);

                // Specular
                float3 reflectDir = reflect(-lightDir, normal);
                float spec = pow(max(dot(viewDir, reflectDir), 0.0), _Shininess);

                // Texture and color
                float4 texColor = tex2D(_MainTex, i.uv);
                float4 color = _Color * texColor;
                color.rgb *= diff;
                color.rgb += spec;

                return color;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

分析说明表

关键点说明示例代码
ShaderLab 结构定义着色器的基本结构,包括名称、属性和渲染过程Shader "Custom/MyShader"
Properties定义在 Inspector 中暴露的变量_MainTex ("Texture", 2D) = "white" {}
SubShader 和 Pass定义具体的渲染步骤SubShader { Pass { CGPROGRAM ... ENDCG } }
顶点着色器处理顶点属性,如位置和法线v2f vert (appdata v)
片段着色器计算每个像素的颜色float4 frag (v2f i) : SV_Target
#pragma 指令控制编译器行为,定义着色器入口#pragma vertex vert
内置变量Unity 提供的内置变量,方便在着色器中使用UNITY_MATRIX_MVP
纹理采样使用 tex2D 函数进行纹理采样float4 texColor = tex2D(_MainTex, i.uv)
多通道渲染使用多个 Pass 进行复杂的渲染SubShader { Pass { ... } Pass { ... } }

总结

ShaderLab 是 Unity 中创建和管理着色器的核心工具。通过理解其基本结构、常用属性和关键技术,开发者可以创建出各种复杂的图形效果。从基础的颜色和纹理处理,到高级的光照和多通道渲染,ShaderLab 提供了强大的功能和灵活性。希望本文记录的关键点能帮助您更好地掌握 ShaderLab,提高图形编程的效率和效果。

蓝易云是一家专注于香港及国内数据中心服务的提供商,提供高质量的服务器租用和云计算服务、包括免备案香港服务器、香港CN2、美国服务器、海外高防服务器、国内高防服务器、香港VPS等。致力于为用户提供稳定,快速的网络连接和优质的客户体验。
最后修改:2024 年 06 月 11 日
如果觉得我的文章对你有用,请随意赞赏