核心知识点:本地 / 世界坐标系、向量点乘叉乘、矩阵变换、DX 与 OpenGL 坐标系差异、MVP 矩阵、五大坐标空间、渲染流水线三大阶段、Shader 文件整体结构、Properties、SubShader、Pass、CGPROGRAM 语义、CG 数据类型、顶点着色器 & 片元着色器基础
一、图形数学前置知识
1 坐标系概念
1 概念
分为本地(模型)坐标系 、世界坐标系 。同一个空间点,在不同坐标系下坐标数值不同;做向量运算,必须保证运算双方处于同一坐标系。
2 特性 & 规则
-
模型建模时自带本地坐标系;
-
世界坐标系是整个场景统一公共坐标系;
-
做计算需要把点 / 向量转换到同一坐标系再运算。
2 向量:点乘、叉乘
1 点乘 (Dot)
-
公式:a·b = |a||b|cosθ
-
几何意义:求 a 向量在 b 向量上的投影;返回结果是标量。
-
判断夹角: 结果 > 0:夹角小于 90°,方向接近; 结果 = 0:两向量垂直; 结果 < 0:夹角大于 90°。
-
Unity API:
Vector3.Dot(a,b)。
2 叉乘 (Cross)
-
公式:a×b = |a||b|sinθ·n
-
几何意义:得到一个垂直于 a、b 所在平面的新向量;可以用来求平面法线、判断朝向。
-
点乘降维度,叉乘升维度;Unity API:
Vector3.Cross(a,b)。
3 单位向量
模长等于 1,只保留方向信息,常用于光照、朝向计算。
4 几何变换两种模式
-
视图变换(坐标模式):图形不变,坐标系发生旋转 / 平移;
-
几何变换(图形模式,项目常用):坐标系不变,物体本身做旋转、缩放、平移。
变换执行顺序:旋转 → 缩放 → 平移。
平移:只改变位置,不改变大小形状; 旋转:改变物体朝向; 缩放:改变物体尺寸,会连带改变坐标。
5 OpenGL 与 DX 坐标系差异
-
OpenGL:笛卡尔右手坐标系;
-
DX (DirectX,微软):2D 下 Y 轴向下;三维空间两者差异更大;
-
Unity 对底层图形库做高层封装,开发者一般不用手写底层图形 API。
6 矩阵基础
概念
矩阵是坐标变换的运算规则;模型大量顶点,使用同一个变换矩阵,批量完成所有顶点坐标转换。
-
方阵:行数等于列数,如 3×3、4×4;
-
单位矩阵:主对角线全部为 1,其余为 0,乘完坐标不变;
-
DX 使用行向量 ;OpenGL 使用列向量,向量左乘 / 右乘矩阵规则不同。
7 MVP 矩阵与五大坐标空间
1 五大坐标空间
-
模型空间 (本地空间):建模时每个模型自带独立坐标系;
-
世界空间:整个场景统一坐标系;
-
观察空间 (摄像机空间):以摄像机为原点的坐标系;
-
剪裁空间:视锥体决定,超出视锥体的物体直接剪裁丢弃不渲染;
-
屏幕空间:最终 2D 屏幕像素坐标。
2 MVP 矩阵含义
M (Model 模型矩阵):模型空间 → 世界空间; V (View 视图矩阵):世界空间 → 观察空间; P (Projection 投影矩阵):观察空间 → 剪裁空间;
剪裁空间之后执行屏幕映射,得到屏幕像素坐标。
3 相关知识点对比
表格
| 空间 | 作用 |
|---|---|
| 模型空间 | 每个模型独立原点,建模输出 |
| 世界空间 | 场景全局统一坐标 |
| 观察空间 | 以摄像机为原点 |
| 剪裁空间 | 视锥体剔除不在视野内图元 |
| 屏幕空间 | 输出 2D 像素画面 |
4 模块拓展
底层 DX 裸 API 绘制一个立方体,手写上千行代码;Unity 封装了矩阵运算,开发者直接使用 MVP 内置变量。
二、渲染流水线宏观划分
1 概念
渲染流水线:把模型顶点数据一步步处理,最终输出屏幕像素画面;分为应用阶段、几何阶段、光栅化阶段。
2 特性 & 规则
-
应用阶段(CPU 执行) 准备模型、贴图数据送入显存; 设置渲染状态; 输出 DrawCall(DC),向 GPU 下发渲染指令。
-
几何阶段(GPU 执行) 顶点着色器为主;完成顶点坐标矩阵变换,输出屏幕空间顶点。
-
光栅化阶段(GPU 执行) 把顶点构成三角形图元,生成片元;片元着色器计算每一个像素颜色;输出屏幕图像。
关系:CPU (负责运算)-应用程序-DC-Shader-DX/OpenGL-GPU(负责图形渲染)
3 流水线细分步骤
-
CPU:顶点数据输入,发出 DrawCall;
-
顶点着色器:完成顶点坐标变换(必选);
-
曲面细分着色器:可选,细分图元;
-
几何着色器:可选,处理图元;
-
裁剪:丢弃视锥体外图元;
-
屏幕映射:顶点转为屏幕坐标;
-
三角形设置、三角形遍历:由顶点生成三角形、生成片元;
-
片元着色器:计算像素颜色;
-
逐片元操作:深度测试、模板测试、混合,输出屏幕最终图像。
4 相关知识点对比
顶点着色器:几何阶段,处理每一个顶点; 片元着色器:光栅化阶段,处理屏幕每一个像素片元。
5 模块拓展
D3D渲染管线:本地坐标-世界坐标-视图坐标-背面拣选-光照-裁剪-投影-视口变换-光栅化
DC (DrawCall) 就是 CPU 发给 GPU 的渲染指令,和之前性能优化知识点串联。
三、Unity Shader 整体文件语法结构
1 概念
Unity Shader 资源文件,搭配 Material 材质球使用;整体由Shader{}根块、Properties属性块、SubShader子着色器、FallBack兜底组成。
2 特性 & 规则
-
Shader "自定义名字"{}:根,名字会出现在材质球下拉列表; -
Properties{}:面板属性声明,暴露参数给 Inspector 材质面板调节;只做声明,CG 代码块内部需要重新定义对应变量。
格式示例:
_Color("颜色",Color) = (1,1,1,1)常见类型:Color 颜色、Vector4 向量、Int整形、Float 浮点数、Range 范围、Texture 2D 纹理、3D Texture 3D纹理; -
SubShader{}子着色器:一个 shader 可以写多个 SubShader;Unity 运行自动挑选当前平台兼容的 SubShader 执行; -
Pass{}通道:写渲染逻辑的单元,一个 SubShader 至少要有 1 个 Pass; -
FallBack "xxx"兜底;所有 SubShader 都不兼容,回退使用指定内置 shader。 -
Pass 内部写
CGPROGRAM ... ENDCG,中间写 CG 着色器语言代码。Shader "Custom/01-shader"{
Properties{
//_变量名("在inspector面板上的名字",变量类型)
_Color("Color",Color)=(1,1,1,1)
}
SubShader{
Pass{
CGPROGRAM
float4 _Color;//所有变量使用前必须重新定义
ENDCG
}
}
FallBack "Diffuse"
}
3 标签与渲染状态(Pass/SubShader 内设置)
Tags{ "RenderType"="Opaque" "Queue"="Geometry" "LightMode"="ForwardBase" "DisableBatching" "IgnoreProjector"="True"}:渲染类型、渲染队列、光照模式、禁用批处理、忽略投影; LOD 200:层级细节; Cull Back/Front/Off:面剔除;Cull Off 关闭剔除,双面都渲染; ZWrite On/Off:深度写入开关; ZTest Less / Greater:深度测试模式。
4 CG 语言基础数据类型(CGPROGRAM 块内)
-
float:32 位高精度浮点数; -
half:16 位半精度,够用优先用 half,性能更好; -
fixed:12 位定点,颜色分量首选; -
int:32 位整型; -
bool布尔; -
float2/float3/float4向量;float4x4矩阵; -
sampler2D / samplerCube / sampler3D:纹理采样器; -
float a[10]:数组; -
struct{};:结构体。
颜色 RGBA4 个分量,优先使用
fixed4。
5 顶点着色器、片元着色器基础
1 编译指令
#pragma vertex vert //指定vert为顶点着色器函数的名称,完成顶点坐标从模型空间到剪裁空间的变换
#pragma fragment frag //指定frag为片元着色器函数的名称,返回模型对应屏幕上的每一个像素的颜色值
2 语义绑定 (semantic)
输入语义:告诉 GPU 把模型数据传给函数参数,如POSITION顶点坐标; 输出语义:告诉 GPU 返回数据用途,SV_POSITION输出剪裁空间坐标;SV_Target输出像素颜色。
3 最简示例代码片段
#pragma vertex vert
#pragma fragment frag
// 顶点输入语义 POSITION
//POSITION:告诉系统,需要把顶点坐标传递给变量v
//SV_POSITION:告诉系统,返回值是剪裁空间下的顶点坐标
float4 vert(float4 pos:POSITION) :SV_POSITION{
// mul矩阵向量乘法,UnityObjectToClipPos等价乘MVP矩阵
return mul(UNITY_MATRIX_MVP,pos);
}
//片元返回颜色给像素 SV_Target
//SV_Target:告诉系统。返回值需要模型对应屏幕上的每一个像素的颜色值
fixed4 frag():SV_Target{
return fixed4(1,0,0,1); //输出红色
}
4 相关知识点对比
Properties 块:仅面板声明;CGPROGRAM 内部必须重新定义同名变量,才能在着色器代码读取。
5 模块拓展
当前示例缺陷:顶点着色器数据无法传递到片元着色器;下午课程讲解结构体传递插值数据。
综合拓展
1 完整知识链路 图形数学(坐标系、点乘叉乘、矩阵)→五大坐标空间→MVP 矩阵 →渲染流水线三大阶段(CPU 应用阶段、GPU 几何、光栅化) →Unity Shader 文件整体结构 Properties / SubShader / Pass / FallBack → CG 语言基础类型 →顶点着色器、片元着色器基础、语义绑定。
2 高频易错清单
-
向量运算不在同一坐标系,计算结果错误;需要先统一坐标空间;
-
Properties 块声明变量,忘记在 CGPROGRAM 块内重新定义,代码拿不到参数;
-
混淆 DX 行向量、OpenGL 列向量,矩阵乘法顺序出错;
-
忘记语义绑定 POSITION/SV_POSITION/SV_Target,GPU 无法传递输入输出数据。
3 核心考点 点乘叉乘几何意义;五大坐标空间;MVP 矩阵作用;渲染流水线三阶段分工(CPU/GPU 分工);Shader 文件整体结构;Properties 作用;Pass 通道;CG 精度类型 fixed/half/float;顶点着色器与片元着色器职责;语义绑定。
4 进阶拓展方向 顶点片元之间结构体传递插值数据、纹理采样、光照模型。