复习Unity shader
一、着色器
着色器的分类:
- 表面着色器
- 顶点或者片元着色器
- 固定函数着色器
ShaderLab 结构:
Shader "MyShader" {
Properties {
_MyTexture ("My Texture", 2D) = "white" { }
// 此处放置其他属性,如颜色或矢量。
}
SubShader {
// 此处放置以下几项的着色器代码:
// - 表面着色器,
// - 顶点和片元着色器,或
// - 固定函数着色器
}
SubShader {
// 此处放置比上面更简单的子着色器版本。
// 此版本用于支持较旧的显卡。
}
}
二、表面着色器
以下是表面着色器的标准输出结构:
struct SurfaceOutput
{
fixed3 Albedo; // 漫射颜色
fixed3 Normal; // 切线空间法线(如果已写入)
fixed3 Emission;
half Specular; // 0..1 范围内的镜面反射能力
fixed Gloss; // 镜面反射强度
fixed Alpha; // 透明度 Alpha
};
表面着色器基于物理的光照模型输出结构:
struct SurfaceOutputStandard
{
fixed3 Albedo; // 基础(漫射或镜面反射)颜色
fixed3 Normal; // 切线空间法线(如果已写入)
half3 Emission;
half Metallic; // 0=非金属,1=金属
half Smoothness; // 0=粗糙,1=平滑
half Occlusion; // 遮挡(默认为 1)
fixed Alpha; // 透明度 Alpha
};
表面着色器标准光照模型和标准镜面反射光照模型输出结构:
struct SurfaceOutputStandardSpecular
{
fixed3 Albedo; // 漫射颜色
fixed3 Specular; // 镜面反射颜色
fixed3 Normal; // 切线空间法线(如果已写入)
half3 Emission;
half Smoothness; // 0=粗糙,1=平滑
half Occlusion; // 遮挡(默认为 1)
fixed Alpha; // 透明度 Alpha
};
表面着色器放置在 CGPROGRAM…ENDCG 代码块内。不同之处在于:
- 它必须放在 SubShader 代码块内,不能在 Pass 内。表面着色器本身将编译为多个通道。
- 它使用 #pragma surface … 指令来指示自己是表面着色器。
#pragma surface 指令为:
# pragma surface surfaceFunction lightModel [optionalparams]
三、顶点、片元着色器
顶点着色器的示例:
Shader "Unlit/Show UVs"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (
float4 vertex : POSITION, // 顶点位置输入
float2 uv : TEXCOORD0 // 第一个纹理坐标输入
)
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
o.uv = uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.uv, 0, 0);
}
ENDCG
}
}
}