[toc]
曲面细分 在渲染流水线中处在顶点着色器之后 片元着色器之前
其功能主要是通过曲面细分来增加模型的细节,通常曲面细分会配合三张图
- 颜色图,即主纹理
- 高度图,即高度映射
- 法线贴图,即顶点的法线方向
在 ShaderLab 的 SurfaceShader 中,如果想声明一个曲面细分函数,需要在预声明中添加 tessellation: 函数名
该函数只需要返回一个整数即可,即细分级别
常见的流程为:通过高度图处理顶点高度 —> 通过曲面细分对顶点进行细分 -> 通过法线贴图对顶点法线进行修改 -> 通过 Color 贴图对顶点进行着色
采样函数: tex2Dlod () [注意 Lod], 是可以指定等级的,这个等级对应 mipmap 的等级,tex2D 只能在片元着色器中采样,而 tex2Dlod () 可以在任意着色器中采样.
# 效果
仅由一个 Unity 内置的 plane 生成
曲面细分
# 代码
Shader “Custom/Tesselation”
{
Properties
{
_MainTex(“Color”, 2D) = “white” {}
_Tessellation(“Tessellation”,Range(1,32)) = 1
_HeightMap(“Height Map”,2D) = “gray” {}
_Height(“Height”,Range(0,1.0)) = 0
\_NormalMap("Normal Map",2D) = "bump" {}
\_Bumpiness("Bumpiness",Range(0,1)) = 0.5
}
SubShader{
CGPROGRAM
//声明曲面细分函数和顶点修改函数的编译指令
#pragma surface surf Lambert tessellate:tessellation vertex:height addshadow
half \_Tessellation;
//固定数量的曲面细分函数,只需要返回曲面细分等级
float4 tessellation() {
return \_Tessellation;
}
sampler2D \_HeightMap;
float4 \_HeightMap\_ST;
fixed \_Height;
//顶点修改函数
void height(inout appdata\_full v) {
float2 texcoord = TRANSFORM\_TEX(v.texcoord, \_HeightMap);
//对\_HeightMap采样,然后乘以\_Height
float h = tex2Dlod(\_HeightMap, float4(texcoord, 0, 0)).r \* \_Height;
//顶点沿着法线方向偏移h
v.vertex.xyz += v.normal \* h;
}
struct Input {
float2 uv\_MainTex;
float2 uv\_NormalMap;
};
sampler2D \_MainTex;
sampler2D \_NormalMap;
fixed \_Bumpiness;
void surf(Input IN, inout SurfaceOutput o) {
half4 c = tex2D(\_MainTex, IN.uv\_MainTex);
o.Albedo = c.rgb;
float3 n = UnpackNormal(tex2D(\_NormalMap, IN.uv\_NormalMap));
n.xy \*= fixed2(\_Bumpiness, \_Bumpiness);
o.Normal = n;
}
ENDCG
}
FallBack "Diffuse"
}
以上是基于数量的曲面细分,还有集中其他的曲面细分方法,但都相差不大。主要是为了性能考虑而提出了,除此之外,还有 phong 曲面细分,这个主要是让模型更光滑.