一、Shader 基础知识
1.1 什么是Shader?
-
定义:Shader(着色器)是运行在GPU上的程序,用于控制3D图形的渲染方式
-
作用:决定物体如何呈现(颜色、光照、纹理、特效等)
-
类型:
-
Vertex Shader(顶点着色器):处理每个顶点的位置
-
Fragment/Pixel Shader(片元/像素着色器):处理每个像素的颜色
-
1.2 Unity中的Shader类型
-
Surface Shader:Unity封装的基于物理的渲染,适合初学者
-
Vertex & Fragment Shader:最灵活,手动控制渲染管线
-
Unlit Shader:无光照Shader,用于UI、特效等
-
Post-processing Shader:后处理特效
二、第一个Shader:纯色Shader
hlsl
Shader "Custom/SimpleColor"
{
Properties
{
// 在Inspector面板中显示的颜色属性
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _Color;
}
ENDCG
}
}
}
三、带纹理的Shader
hlsl
Shader "Custom/SimpleTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
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;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
四、基础光照Shader
hlsl
Shader "Custom/BasicDiffuse"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNormal : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// 采样纹理
fixed4 col = tex2D(_MainTex, i.uv) * _Color;
// 环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 漫反射
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float diff = max(0, dot(normalize(i.worldNormal), lightDir));
fixed3 diffuse = _LightColor0.rgb * diff;
// 最终颜色
fixed3 finalColor = (ambient + diffuse) * col.rgb;
return fixed4(finalColor, 1);
}
ENDCG
}
}
}
五、ShaderLab 语法详解
5.1 Properties 属性块
hlsl
Properties
{
// 基本类型
_Int ("Int", Int) = 2
_Float ("Float", Float) = 1.5
_Range ("Range", Range(0.0, 1.0)) = 0.5
// 颜色和向量
_Color ("Color", Color) = (1,1,1,1)
_Vector ("Vector", Vector) = (0,0,0,0)
// 纹理
_2D ("2D Texture", 2D) = "white" {}
_Cube ("Cube Map", Cube) = "white" {}
_3D ("3D Texture", 3D) = "white" {}
}
5.2 SubShader 和 Pass
-
SubShader:针对不同显卡配置的备用方案
-
Pass:一次完整的渲染过程,一个SubShader可以有多个Pass
-
Tags:控制渲染顺序、类型等
六、实用特效示例
6.1 顶点动画(水波效果)
hlsl
Shader "Custom/VertexAnimation"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Amplitude ("Amplitude", Range(0, 1)) = 0.1
_Frequency ("Frequency", Range(0, 10)) = 1
_Speed ("Speed", Range(0, 5)) = 1
}
SubShader
{
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;
};
sampler2D _MainTex;
float _Amplitude, _Frequency, _Speed;
v2f vert (appdata v)
{
v2f o;
// 顶点动画:正弦波
float wave = sin(v.vertex.x * _Frequency + _Time.y * _Speed) * _Amplitude;
v.vertex.y += wave;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
6.2 边缘光效果
hlsl
Shader "Custom/RimLight"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_RimColor ("Rim Color", Color) = (1,1,1,1)
_RimPower ("Rim Power", Range(0.5, 8)) = 3
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input
{
float2 uv_MainTex;
float3 viewDir;
float3 worldNormal;
};
sampler2D _MainTex;
float4 _RimColor;
float _RimPower;
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
// 计算边缘光强度
float rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
o.Emission = _RimColor.rgb * pow(rim, _RimPower);
}
ENDCG
}
}
七、学习路径建议
第一阶段:基础(1-2周)
-
理解渲染管线流程
-
掌握ShaderLab基本结构
-
学会编写简单颜色和纹理Shader
第二阶段:进阶(1-2个月)
-
学习光照模型(Lambert, Phong, Blinn-Phong)
-
理解法线贴图、高光、环境光等概念
-
掌握Surface Shader编写
第三阶段:高级(3-6个月)
-
学习屏幕后处理
-
掌握Shader优化技巧
-
学习Shader Graph可视化编程
第四阶段:专业
-
学习PBR(基于物理的渲染)
-
掌握复杂特效(如体积光、次表面散射等)
-
学习Compute Shader
八、调试技巧
hlsl
// 1. 使用颜色调试
return float4(i.uv, 0, 1); // 查看UV坐标
return float4(normal, 0.5); // 查看法线方向
// 2. Unity Shader Debugger
// 使用Frame Debugger和RenderDoc工具
// 3. 添加调试参数
_DebugMode ("Debug Mode", Range(0, 3)) = 0
// 在frag函数中
if(_DebugMode == 0) return col;
else if(_DebugMode == 1) return float4(normal, 1);
九、常用资源
学习资料:
-
官方文档:Unity ShaderLab Reference
-
书籍:《Unity Shader入门精要》
-
网站:
-
ShaderToy(学习GLSL)
-
知乎/CSDN相关专栏
-
工具:
-
Shader Graph:Unity可视化Shader编辑器
-
Amplify Shader Editor:第三方Shader编辑器
-
RenderDoc:图形调试工具
十、注意事项
-
性能优化:
-
减少纹理采样次数
-
避免分支语句(if/for)
-
使用half/fixed代替float
-
-
平台兼容性:
-
注意移动平台精度限制
-
测试不同GPU支持度
-
使用multi_compile处理变体
-
-
常见错误:
-
忘记声明变量
-
坐标系转换错误
-
光照模式不匹配
-
这个入门指南涵盖了Unity Shader的基础知识。建议从最简单的纯色Shader开始,逐步增加复杂度,多动手实践,结合具体项目需求学习特定效果。