着色器
概念
Shader(着色器)是运行在GPU上的小程序,控制物体渲染时的光照、颜色、纹理等视觉效果。它决定了材质如何与光线交互,生成最终像素颜色。
核心功能:
- 顶点变换(如模型空间→屏幕空间)。
- 光照计算(漫反射、高光、环境光)。
- 纹理映射与混合(如法线贴图、透明度处理)。
Shader与材质的关系
- Shader:是“食谱”,定义渲染规则(如光照模型、混合模式)。
- 材质:是“菜肴”,绑定Shader并设置具体参数(如颜色、纹理)。
- 关系链:Shader → 材质 → 网格渲染器(Mesh Renderer)。
面试题
1. Unity中Shader的常见类型及区别?
答案:
- Surface Shader:封装了光照模型(如PBR),适合物理渲染(如金属、塑料)。
- Unlit Shader:忽略光照,用于UI、特效(如发光粒子)。
- Vertex/Fragment Shader:完全自定义渲染流程,适合高级效果(如扭曲、溶解)。
- Shader Graph:节点化编辑,无需代码(如卡通渲染)。
2. 编写一个简单的Unlit Shader
(输出固定颜色,不受光照影响)。
Shader "Custom/UnlitColor" {
Properties { _Color ("Color", Color) = (1,1,1,1) }
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata { float4 vertex : POSITION; };
struct v2f { float4 pos : SV_POSITION; };
fixed4 _Color;
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target { return _Color; }
ENDCG
}
}
}
3. 顶点着色器与片元着色器的分工?
- 顶点着色器:处理几何数据(如顶点位置、法线、UV)。
- 片元着色器:计算像素颜色(如纹理采样、光照混合)。
- 示例:顶点着色器可扭曲网格,片元着色器实现渐变透明。
4. 如何优化Shader性能?
方法:
- 减少分支:避免
if-else,使用step()或插值替代。 - 简化计算:用
half代替float,预计算常量。 - 合批优化:相同Shader Variant的材质可合批减少DrawCall。
5. PBR材质的关键属性有哪些?
答案:
- Albedo:基础颜色(反照率)。
- Metallic:金属度(0-1)。
- Smoothness:光滑度(影响高光范围)。
- Normal Map:表面凹凸模拟。
6. ShaderLab中Properties的作用?
答案:
- 定义材质Inspector中可调参数(如颜色、纹理)。
- 示例:
_MainTex ("Texture", 2D) = "white" {}声明一张默认白色纹理。
7. 如何实现溶解效果?
-
Shader方案:
-
使用噪声图控制透明度阈值:
clip(noise.r - _Threshold); // 裁剪低于阈值的像素
- 动态调整
_Threshold实现溶解动画。
8. Unity内置渲染管线与SRP的区别?
- 内置管线:固定流程,支持Surface Shader。
- SRP(如URP/HDRP):可编程管线,支持Shader Graph,优化移动端(URP)或高端图形(HDRP)。
9. 什么是Shader Variant?如何管理?
答案:
- 同一Shader的不同编译版本(如不同光照、关键字组合)。
- 管理:通过
#pragma multi_compile定义变体,避免冗余变体增加包体。
10. 动态修改材质颜色的最佳实践?
方案:
- MaterialPropertyBlock:修改属性不创建新材质实例:
(避免内存碎片)
MaterialPropertyBlock props = new MaterialPropertyBlock();
props.SetColor("_Color", Color.red);
GetComponent<Renderer>().SetPropertyBlock(props);
11. 法线贴图与视差贴图的原理差异?
- 法线贴图:通过RGB编码法线方向,模拟凹凸(不改变几何)。
- 视差贴图:根据高度偏移UV,产生深度错觉(性能开销更高)。
12. 几何着色器(Geometry Shader)的应用场景?
- 答案:动态生成几何体(如毛发、草地),但移动端支持有限。
13. Shader中如何实现卡通渲染(Cel Shading)?
-
关键步骤:
-
离散化光照(
floor(dot(N,L) * 3) / 3)。 -
边缘检测(法线与视角夹角描边)。