1 前言
上文介绍了渲染管线、固定管线着色器和表面着色器,如下:
固定管线着色器通过命令方式实现光照和贴图等效果,表面着色器通过给 SurfaceOutput 赋值实现光照、贴图和法线贴图等效果,它们都不用关注光照算法是如何实现的,只需要传值就行。
顶点和片元着色器给用户提供了更灵活的用法,但使用也更困难。另外,顶点着色器可以通过控制 MVP 矩阵变换实现对模型位置和姿态的控制。
2 固定颜色
在 Assets 窗口右键,依次选择【Create→Shader→Standard Surface Shader】创建 Shader 脚本,实现固定颜色 Shader 代码如下:
VFShader.shader
Shader "MyShader/VFShaderTest" {
Properties
{
// 属性名 ("面板显示名称", 类型) = 默认值
_MainColor ("显示颜色", Color) = (1, 0, 0, 1)
}
SubShader
{
Pass
{
CGPROGRAM // CG语言的开始
// 编译指令 着色器名称 函数名称
#pragma vertex vert // 顶点着色器, 每个顶点执行一次
#pragma fragment frag // 片段着色器, 每个像素执行一次
// 导入头文件
#include "UnityCG.cginc"
// 声明属性变量, 必须与外部属性变量名称一致
fixed4 _MainColor;
// 顶点着色器
half4 vert(half4 vertexPos: POSITION): SV_POSITION
{
// 将局部坐标系下坐标转换为裁剪坐标系下坐标
return UnityObjectToClipPos(vertexPos); // 等价于: mul(UNITY_MATRIX_MVP, vertexPos)
}
// 片元着色器
fixed4 frag(): COLOR
{
return _MainColor;
}
ENDCG // CG语言的结束
}
}
FallBack "Diffuse"
}
创建一个 Material,并将 ShaderTest 绑定到该 Material 上,如下:
将该 Material 拖拽到一个 Cube 和 Sphere 游戏对象上。选中绑定的 Material,在 Inspector 窗口调整 Shader 中固定颜色,显示效果如下:
3 光照
VFShader.shader
Shader "MyShader/VFShaderTest" {
Properties
{
// 属性名 ("面板显示名称", 类型) = 默认值
_DiffuseColor ("漫反射颜色", Color) = (1, 0, 0, 1)
}
SubShader
{
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM // CG语言的开始
// 编译指令 着色器名称 函数名称
#pragma vertex vert // 顶点着色器, 每个顶点执行一次
#pragma fragment frag // 片段着色器, 每个像素执行一次
// 导入头文件
#include "UnityCG.cginc"
// 声明属性变量, 必须与外部属性变量名称一致
fixed4 _DiffuseColor;
struct appdata // 顶点着色器输入结构体
{
half4 vertexPos: POSITION; // 局部坐标系下顶点坐标
half3 vertexNormal: NORMAL; // 局部坐标系下顶点法线向量
};
struct v2f // 顶点着色器输出结构体
{
half4 clipPos: SV_POSITION; // 裁剪坐标系下顶点坐标
half3 worldNormal: Normal; // 裁剪坐标系下顶点法线向量
half3 worldLightDir : TEXCOORD0; // 光照方向
};
// 顶点着色器
v2f vert(appdata data)
{
v2f o;
o.clipPos = UnityObjectToClipPos(data.vertexPos); // 等价于: mul(UNITY_MATRIX_MVP, data.vertexPos)
o.worldNormal = UnityObjectToWorldNormal(data.vertexNormal); // 将局部坐标系下法线转换为世界坐标系下法线
o.worldLightDir = UnityWorldSpaceLightDir(data.vertexPos); // 计算世界坐标系下顶点指向光源的向量
return o;
}
// 片元着色器
fixed4 frag(v2f input): COLOR
{
half factor = dot(input.worldNormal, input.worldLightDir);
//return _DiffuseColor * factor + UNITY_LIGHTMODEL_AMBIENT; // Lambert光照模型
return _DiffuseColor * (0.5 * factor + 0.5) + UNITY_LIGHTMODEL_AMBIENT; // 半Lambert光照模型
}
ENDCG // CG语言的结束
}
}
FallBack "Diffuse"
}
选中绑定的 Material,在 Inspector 窗口调整 Shader 中光照颜色,显示效果如下:
4 贴图
VFShader.shader
Shader "MyShader/VFShaderTest" {
Properties
{
// 属性名 ("面板显示名称", 类型) = 默认值
_MainTex ("2阶贴图", 2D) = "white" {}
}
SubShader
{
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM // CG语言的开始
// 编译指令 着色器名称 函数名称
#pragma vertex vert // 顶点着色器, 每个顶点执行一次
#pragma fragment frag // 片段着色器, 每个像素执行一次
// 导入头文件
#include "UnityCG.cginc"
// 声明属性变量, 必须与外部属性变量名称一致
sampler2D _MainTex;
struct appdata // 顶点着色器输入结构体
{
half4 vertexPos: POSITION; // 顶点坐标
half2 uv_MainTex: TEXCOORD0; // 纹理uv坐标
};
struct v2f // 顶点着色器输出结构体
{
half4 clipPos: SV_POSITION; // 屏幕坐标
half2 uv_MainTex: TEXCOORD0; // 纹理uv坐标
};
// 顶点着色器
v2f vert(appdata data)
{
v2f o;
o.clipPos = UnityObjectToClipPos(data.vertexPos); // 等价于: mul(UNITY_MATRIX_MVP, data.vertexPos)
o.uv_MainTex = data.uv_MainTex;
return o;
}
// 片元着色器
fixed4 frag(v2f input): COLOR
{
return tex2D(_MainTex, input.uv_MainTex);
}
ENDCG // CG语言的结束
}
}
FallBack "Diffuse"
}
选中绑定的 Material,在 Inspector 窗口选择贴图图片,显示效果如下:
声明:本文转自【Unity3D】顶点和片元着色器
标签:Unity3D,MainTex,Shader,片元,vertexPos,顶点,data,着色器 From: https://www.cnblogs.com/zhyan8/p/17237932.html