# 游戏渲染管线与着色器
## 概述
渲染管线(Rendering Pipeline)是将3D场景转换为2D图像的一系列处理步骤。理解渲染管线对于优化性能、实现视觉效果和跨平台开发至关重要。
---
## 1. 渲染管线基础
### 1.1 Forward Rendering(前向渲染)
**原理**:对每个物体,遍历所有光源计算光照
```
对于每个物体:
对于每个像素:
对于每个光源:
计算光照贡献
累加所有光照
```
**优点**:
- 简单直观
- 支持透明物体
- 内存占用低
**缺点**:
- 光源数量增加时性能急剧下降(O(n×m))
- 重复计算(多个物体在同一像素)
**适用场景**:
- 移动游戏
- 光源少的场景
- 需要大量透明物体的游戏
### 1.2 Deferred Rendering(延迟渲染)
**原理**:先渲染几何信息到G-Buffer,再统一计算光照
```
Pass 1 - 几何 Pass:
渲染所有物体到 G-Buffer
G-Buffer 包含:位置、法线、颜色、材质属性
Pass 2 - 光照 Pass:
对每个光源:
在光源影响范围内计算光照
读取 G-Buffer 数据
```
**优点**:
- 光源数量对性能影响小
- 每个像素只计算一次几何
- 适合大量光源场景
**缺点**:
- 内存占用高(G-Buffer)
- 不支持 MSAA(多重采样抗锯齿)
- 透明物体需要单独处理
**适用场景**:
- 开放世界游戏
- 室内场景(多光源)
- PC/主机游戏
### 1.3 Forward+ / Tiled Forward Rendering
**原理**:结合 Forward 和 Deferred 的优点
```
1. 将屏幕划分为 Tile(通常 16x16 像素)
2. 对每个 Tile,计算影响它的光源列表
3. 前向渲染,但每个像素只计算相关光源
```
**优点**:
- 支持大量光源(比 Forward 多)
- 支持 MSAA
- 支持透明物体
- 内存占用适中
**适用场景**:
- 现代游戏的主流选择
- Unity URP、Unreal 默认管线
### 1.4 Clustered Rendering
**原理**:在 Tile 的基础上增加深度维度
```
1. 将视锥体划分为 3D 簇(Cluster)
2. 每个 Cluster 存储影响它的光源列表
3. 渲染时根据像素深度确定 Cluster,只计算相关光源
```
**优点**:
- 支持极大量光源
- 更好的深度剔除
- 适合复杂室内场景
**适用场景**:
- 高端 PC/主机
- Unity HDRP、Unreal 5
### 1.5 管线对比
| 特性 | Forward | Deferred | Forward+ | Clustered |
|------|---------|----------|----------|-----------|
| **光源数量** | < 10 | 100+ | 100+ | 1000+ |
| **透明物体** | 原生支持 | 需额外处理 | 原生支持 | 原生支持 |
| **MSAA** | 支持 | 不支持 | 支持 | 支持 |
| **内存占用** | 低 | 高 | 中 | 中 |
| **带宽** | 低 | 高 | 中 | 中 |
| **复杂度** | 低 | 中 | 中 | 高 |
---
## 2. 着色器编程
### 2.1 着色器类型
| 类型 | 阶段 | 用途 |
|------|------|------|
| **Vertex Shader** | 顶点处理 | 变换、变形、骨骼动画 |
| **Fragment/Pixel Shader** | 片元处理 | 光照、纹理采样、颜色计算 |
| **Geometry Shader** | 图元处理 | 生成额外几何(粒子、毛发) |
| **Compute Shader** | 通用计算 | 后处理、物理、AI |
| **Tessellation Shader** | 细分处理 | 动态 LOD、曲面细分 |
### 2.2 HLSL 示例(Unity/Unreal)
```hlsl
// 基础 PBR 片元着色器(HLSL)
struct VertexInput
{
float4 position : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct VertexOutput
{
float4 position : SV_POSITION;
float3 worldNormal : NORMAL;
float2 uv : TEXCOORD0;
float3 worldPosition : TEXCOORD1;
};
// 顶点着色器
VertexOutput VertexShader(VertexInput input)
{
VertexOutput output;
output.position = mul(UNITY_MATRIX_MVP, input.position);
output.worldNormal = mul((float3x3)unity_ObjectToWorld, input.normal);
output.uv = input.uv;
output.worldPosition = mul(unity_ObjectToWorld, input.position).xyz;
return output;
}
// 片元着色器
float4 FragmentShader(VertexOutput input) : SV_TARGET
{
// 采样纹理
float4 albedo = tex2D(_MainTex, input.uv);
float3 normal = normalize(input.worldNormal);
// 基础光照计算(Lambert)
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float NdotL = max(dot(normal, lightDir), 0);
// 最终颜色
float3 diffuse = albedo.rgb * NdotL * _LightColor0.rgb;
float3 ambient = albedo.rgb * UNITY_LIGHTMODEL_AMBIENT.rgb;
return float4(diffuse + ambient, albedo.a);
}
```
### 2.3 GLSL 示例(OpenGL/WebGL)
```glsl
// 顶点着色器(GLSL)
#version 300 es
in vec3 a_position;
in vec3 a_normal;
in vec2 a_uv;
uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix;
uniform mat4 u_projectionMatrix;
out vec3 v_worldNormal;
out vec2 v_uv;
out vec3 v_worldPosition;
void main()
{
vec4 worldPosition = u_modelMatrix * vec4(a_position, 1.0);
gl_Position = u_projectionMatrix * u_viewMatrix * worldPosition;
v_worldNormal = mat3(u_modelMatrix) * a_normal;
v_uv = a_uv;
v_worldPosition = worldPosition.xyz;
}
// 片元着色器(GLSL)
#version 300 es
precision highp float;
in vec3 v_worldNormal;
in vec2 v_uv;
in vec3 v_worldPosition;
uniform sampler2D u_mainTex;
uniform vec3 u_lightDir;
uniform vec3 u_lightColor;
out vec4 fragColor;
void main()
{
vec4 albedo = texture(u_mainTex, v_uv);
vec3 normal = normalize(v_worldNormal);
float NdotL = max(dot(normal, -u_lightDir), 0.0);
vec3 diffuse = albedo.rgb * NdotL * u_lightColor;
fragColor = vec4(diffuse, albedo.a);
}
```
### 2.4 Shader Graph / 可视化着色器
| 工具 | 引擎 | 特点 |
|------|------|------|
| **Shader Graph** | Unity | 节点图,支持 URP/HDRP |
| **Material Editor** | Unreal | 节点图,功能强大 |
| **VisualShader** | Godot | 节点图,轻量 |
---
## 3. 光照模型
### 3.1 PBR(基于物理的渲染)
PBR 是现代游戏的标准光照模型,基于物理原理而非经验公式。
**核心概念**:
- **Albedo(反照率)**:基础颜色,无光照信息
- **Metallic(金属度)**:0 = 非金属,1 = 金属
- **Roughness(粗糙度)**:0 = 镜面,1 = 漫反射
- **Normal(法线)**:表面微观几何
- **AO(环境光遮蔽)**:自遮挡阴影
**工作流程**:
| 工作流 | Albedo | Specular | 特点 |
|--------|--------|----------|------|
| **Metallic-Roughness** | 包含金属色 | 自动生成 | 更常见,更直观 |
| **Specular-Glossiness** | 纯漫反射 | 单独贴图 | 更灵活,但易出错 |
```hlsl
// 简化的 PBR 漫反射计算
float3 Diffuse_Lambert(float3 albedo)
{
return albedo / PI;
}
// 简化的 PBR 镜面反射(Blinn-Phong 近似)
float3 Specular_BlinnPhong(float3 specularColor, float roughness, float3 normal, float3 viewDir, float3 lightDir)
{
float3 halfDir = normalize(lightDir + viewDir);
float NdotH = max(dot(normal, halfDir), 0);
float specPower = exp2(10 * (1 - roughness) + 1);
return specularColor * pow(NdotH, specPower);
}
```
### 3.2 IBL(基于图像的光照)
使用环境贴图模拟间接光照:
```
环境 HDR 贴图
↓
预计算漫反射辐照度(Irradiance Map)
预计算镜面反射(Prefiltered Mipmaps)
↓
运行时采样
```
### 3.3 Ray Tracing(光线追踪)
实时光线追踪是现代 GPU 的重要特性:
| 效果 | 说明 | 性能影响 |
|------|------|----------|
| **Ray Traced Reflections** | 精确反射 | 高 |
| **Ray Traced Shadows** | 柔和阴影 | 中 |
| **Ray Traced GI** | 全局光照 | 极高 |
| **Ray Traced Ambient Occlusion** | 环境光遮蔽 | 中 |
**硬件支持**:
- NVIDIA RTX(Turing+)
- AMD RDNA2+
- Intel Arc
### 3.4 Global Illumination(全局光照)
| 技术 | 原理 | 质量 | 性能 |
|------|------|------|------|
| **Lightmap** | 预计算静态光照 | 高 | 运行时零开销 |
| **Light Probe** | 预计算动态物体采样点 | 中 | 低 |
| **Realtime GI** | 实时计算间接光 | 中 | 高 |
| **Lumen**(Unreal 5) | 软件光线追踪 | 高 | 中高 |
| **DDGI** | 动态漫反射全局光照 | 高 | 中 |
---
## 4. 后处理技术
### 4.1 常见后处理效果
| 效果 | 说明 | 性能 |
|------|------|------|
| **Bloom** | 高亮区域泛光 | 中 |
| **SSAO** | 屏幕空间环境光遮蔽 | 中 |
| **TAA** | 时域抗锯齿 | 中 |
| **Motion Blur** | 运动模糊 | 中 |
| **Depth of Field** | 景深 | 高 |
| **Chromatic Aberration** | 色差 | 低 |
| **Vignette** | 暗角 | 低 |
| **Color Grading** | 调色 | 低 |
### 4.2 抗锯齿技术
| 技术 | 原理 | 质量 | 性能 | 模糊 |
|------|------|------|------|------|
| **MSAA** | 多重采样 | 高 | 高 | 无 |
| **FXAA** | 快速近似 | 低 | 极低 | 有 |
| **SMAA** | 形态学抗锯齿 | 中 | 低 | 轻微 |
| **TAA** | 时域累积 | 高 | 中 | 轻微 |
| **DLSS/FSR/XeSS** | AI/算法超采样 | 极高 | 负(提升性能) | 无 |
### 4.3 超采样技术
| 技术 | 厂商 | 原理 | 性能提升 |
|------|------|------|----------|
| **DLSS** | NVIDIA | AI 重建高分辨率 | 2-3x |
| **FSR** | AMD | 算法 upscale | 2x |
| **XeSS** | Intel | AI/算法混合 | 2x |
| **TSR** | Unreal | 时域超分辨率 | 2x |
---
## 5. 性能优化
### 5.1 Draw Call 优化
| 技术 | 原理 | 效果 |
|------|------|------|
| **Static Batching** | 合并静态物体 | 减少 Draw Call |
| **Dynamic Batching** | 运行时合并小物体 | 减少 Draw Call |
| **GPU Instancing** | 一次绘制多个相同物体 | 大幅减少 Draw Call |
| **SRP Batcher** | 持续绑定材质数据 | 减少 CPU 开销 |
| **GPU Driven Rendering** | GPU 直接处理剔除 | 极大量物体 |
```csharp
// Unity GPU Instancing 示例
public class GPUInstancing : MonoBehaviour
{
public Mesh mesh;
public Material material;
public int instanceCount = 1000;
private Matrix4x4[] matrices;
void Start()
{
matrices = new Matrix4x4[instanceCount];
for (int i = 0; i < instanceCount; i++)
{
Vector3 position = Random.insideUnitSphere * 50f;
Quaternion rotation = Random.rotation;
Vector3 scale = Vector3.one * Random.Range(0.5f, 2f);
matrices[i] = Matrix4x4.TRS(position, rotation, scale);
}
// 启用 GPU Instancing
material.enableInstancing = true;
}
void Update()
{
// 批量绘制
Graphics.DrawMeshInstanced(mesh, 0, material, matrices);
}
}
```
### 5.2 遮挡剔除(Occlusion Culling)
```csharp
// Unity 遮挡剔除设置
public class OcclusionCullingSetup : MonoBehaviour
{
void Start()
{
// 标记为静态遮挡物
gameObject.isStatic = true;
// 烘焙遮挡剔除数据
// Window -> Rendering -> Occlusion Culling -> Bake
}
}
```
### 5.3 LOD(Level of Detail)
```csharp
// Unity LOD Group 设置
public class LODSetup : MonoBehaviour
{
void Start()
{
LODGroup lodGroup = gameObject.AddComponent
LOD[] lods = new LOD[3];
// LOD 0:0-50% 距离,高质量模型
lods[0] = new LOD(0.5f, new Renderer[] { highQualityMesh });
// LOD 1:50-20% 距离,中质量模型
lods[1] = new LOD(0.2f, new Renderer[] { mediumQualityMesh });
// LOD 2:20% 以下距离,低质量模型/ Billboard
lods[2] = new LOD(0.05f, new Renderer[] { lowQualityMesh });
lodGroup.SetLODs(lods);
lodGroup.RecalculateBounds();
}
}
```
### 5.4 性能预算检查清单
| 指标 | 移动端 | PC | 主机 |
|------|--------|-----|------|
| Draw Calls | < 100 | < 2000 | < 5000 |
| 三角面数 | < 100K | < 5M | < 10M |
| 纹理内存 | < 200MB | < 2GB | < 4GB |
| Shader 复杂度 | 简单 | 复杂 | 复杂 |
| 后处理 | 少量 | 完整 | 完整 |
---
## 6. 跨平台渲染
### 6.1 图形 API 对比
| API | 平台 | 特点 |
|-----|------|------|
| **DirectX 12** | Windows/Xbox | 低开销,多线程 |
| **Vulkan** | 跨平台 | 低开销,显式控制 |
| **Metal** | Apple | 低开销,Apple 优化 |
| **OpenGL ES** | 移动端 | 广泛支持,逐渐淘汰 |
| **WebGPU** | Web | 现代 Web 图形 |
### 6.2 跨平台着色器
```hlsl
// Unity ShaderLab - 跨平台着色器
Shader "Custom/CrossPlatform"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
// Unity 自动处理平台差异
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
float4 _Color;
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = input.uv;
return output;
}
half4 frag(Varyings input) : SV_TARGET
{
half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
return col * _Color;
}
ENDHLSL
}
}
}
```
---
## 7. 典型游戏渲染案例分析
### 7.1 《赛博朋克 2077》
**渲染技术**:
- 光线追踪反射/阴影/全局光照
- DLSS 2.0/3.0
- 复杂的材质系统
- 大规模开放世界流送
### 7.2 《艾尔登法环》
**渲染技术**:
- 自定义引擎(FromSoftware)
- 大气散射
- 动态天气
- 大规模地形渲染
### 7.3 《原神》
**渲染技术**:
- Unity 自定义渲染管线
- 卡通渲染(Toon Shading)
- 跨平台优化(移动/PC/主机)
- 动态分辨率
**卡通渲染关键**:
```hlsl
// 卡通着色器核心
half4 ToonShading(float3 normal, float3 lightDir, half4 albedo)
{
half NdotL = dot(normal, lightDir);
// 硬边光影(而非平滑过渡)
half toonRamp = smoothstep(0.0, 0.1, NdotL);
// 多级阴影
if (NdotL < 0.3) toonRamp = 0.3; // 暗部
else if (NdotL < 0.6) toonRamp = 0.6; // 中间调
else toonRamp = 1.0; // 亮部
// 边缘光(Rim Light)
half rim = 1.0 - saturate(dot(viewDir, normal));
half3 rimColor = pow(rim, 3) * _RimColor;
return half4(albedo.rgb * toonRamp + rimColor, albedo.a);
}
```
---
## 8. 渲染系统检查清单
### 8.1 设计阶段
- [ ] 确定目标平台和性能预算
- [ ] 选择渲染管线(Forward/Deferred/Forward+)
- [ ] 定义视觉风格(写实/卡通/像素)
- [ ] 规划光照策略(实时光/烘焙/混合)
### 8.2 实现阶段
- [ ] 设置渲染管线
- [ ] 创建主着色器
- [ ] 配置光照系统
- [ ] 实施后处理效果
- [ ] 设置 LOD 系统
### 8.3 优化阶段
- [ ] 分析 Draw Call
- [ ] 优化材质和着色器
- [ ] 配置遮挡剔除
- [ ] 压缩纹理
- [ ] 测试目标平台性能
---
## 参考来源
- Unity Scriptable Render Pipeline 官方文档
- Unreal Rendering 官方文档
- Godot Rendering 官方文档
- 《Real-Time Rendering》— Tomas Akenine-Möller
- 《Physically Based Rendering》— Matt Pharr
- GDC 演讲:《The Rendering of The Last of Us Part II》
- SIGGRAPH 论文:各种渲染技术