14.表面着色器-实例分析-顶点膨胀
14.1 知识点
表面着色器中如何处理顶点
在表面着色器的编译指令中,可以通过可选额外参数添加顶点处理函数,用于对顶点进行预处理。
例如,在编译指令中添加 vertex:自定义函数名
,要求自定义的顶点函数格式为:
void 自定义函数名(inout appdata_full v)
实现顶点膨胀效果
主要步骤
- 在Lesson13已有法线贴图代码的基础上进行修改
- 加入顶点碰撞控制参数
- 在编译指令中添加顶点处理函数
- 自定义顶点处理函数,在该函数中对顶点进行偏移
加入顶点碰撞控制参数 _Expansion 并进行映射
在材质属性中定义扩展参数:
Properties
{
// …
_Expansion("Expansion", Float) = 0 // 顶点沿法线方向的偏移量(扩展效果)
}
并声明对应变量:
float _Expansion; // 控制顶点扩展效果
在编译指令中加入顶点处理函数
使用物理基础的标准光照模型,启用全前向阴影,并指定自定义顶点函数:
#pragma surface surf Standard fullforwardshadows vertex:vertexFunc
自定义顶点处理函数
在顶点着色阶段对顶点进行偏移,实现几何体“膨胀”效果:
// 自定义顶点函数:在顶点着色阶段对顶点进行偏移
void vertexFunc(inout appdata_full v)
{
// 顶点坐标沿法线方向偏移,实现几何体“膨胀”效果
v.vertex.xyz += v.normal * _Expansion;
}
修改参数查看效果
调整 _Expansion 参数,可直观观察几何体顶点沿法线方向的膨胀效果。
感受最终颜色处理函数
主要步骤
在可选额外参数中添加颜色处理函数 finalcolor,自定义的颜色函数格式为:
void 自定义函数名(Input IN, SurfaceOutput... o, inout fixed4 color)
在编译指令中指定颜色函数
使用物理基础的标准光照模型,启用全前向阴影,并同时指定自定义顶点和颜色处理函数:
#pragma surface surf Standard fullforwardshadows vertex:vertexFunc finalcolor:colorFunc
表面函数中漫反射阶段不叠加基础颜色
表面函数负责计算每个像素的材质属性,修改Albedo赋值,o.Albedo = texColor.rgb代表先不叠加颜色。Lesson13是直接o.Albedo = texColor.rgb * _Color.rgb;叠加颜色的。
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = texColor.rgb; // 漫反射颜色直接使用基础纹理的颜色
o.Alpha = texColor.a * _Color.a; // 透明度受基础颜色的 alpha 影响
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); // 通过法线贴图解包得到切线空间法线
// o.Emission = _Emission.rgb; // 发光效果(暂未启用)
o.Metallic = _Metallic;
o.Smoothness = _Smoothness;
}
在自定义颜色函数中叠加基础颜色
自定义颜色函数在片元着色阶段调整最终输出颜色,在计算完成后将基础颜色叠加到结果上:
void colorFunc(Input IN, SurfaceOutputStandard o, inout fixed4 color)
{
// 最终输出颜色乘以基础颜色,实现颜色调节
color *= _Color;
}
查看效果
通过调整相关参数和观察 Shader 在场景中的表现,查看顶点膨胀与颜色叠加效果。
14.2 知识点代码
Lesson14.shader
Shader "Custom/Lesson14"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1) // 材质基础颜色
_MainTex ("Albedo (RGB)", 2D) = "white" {} // 基础纹理
_BumpMap("BumpMap", 2D) = ""{} // 法线贴图
//_Emission("Emission", Color) = (1,1,1,1) // 发光属性(暂未启用)
_Metallic("Metallic", Range(0,1)) = 0 // 金属度
_Smoothness("Smoothness", Range(0,1)) = 0 // 平滑度
_Expansion("Expansion", Float) = 0 // 顶点沿法线方向的偏移量(扩展效果)
}
SubShader
{
Tags { "RenderType"="Opaque" } // 标记为不透明材质
CGPROGRAM
// 使用物理基础的标准光照模型,启用全前向阴影,并指定自定义顶点和颜色函数
#pragma surface surf Standard fullforwardshadows vertex:vertexFunc finalcolor:colorFunc
#pragma target 3.0 // 指定Shader Model 3.0
fixed4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
//fixed4 _Emission;
fixed _Metallic;
fixed _Smoothness;
float _Expansion; // 控制顶点扩展效果
// 输入结构体:包含用于采样纹理的UV坐标
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
};
// 表面函数:计算每个像素的材质属性
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = texColor.rgb; // 漫反射颜色直接使用基础纹理的颜色
o.Alpha = texColor.a * _Color.a; // 透明度受基础颜色的alpha影响
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); // 通过法线贴图解包得到切线空间法线
//o.Emission = _Emission.rgb; // 发光效果(暂未启用)
o.Metallic = _Metallic;
o.Smoothness = _Smoothness;
}
// 自定义顶点函数:在顶点着色阶段对顶点进行偏移
void vertexFunc(inout appdata_full v)
{
// 顶点坐标沿法线方向偏移,实现几何体“膨胀”效果
v.vertex.xyz += v.normal * _Expansion;
}
// 自定义颜色函数:在片元着色阶段调整最终输出颜色
void colorFunc(Input IN, SurfaceOutputStandard o, inout fixed4 color)
{
// 最终输出颜色乘以基础颜色,实现颜色调节
color *= _Color;
}
ENDCG
}
FallBack "Diffuse" // 当当前Shader不可用时使用Diffuse Shader作为后备
}
Lesson14_表面着色器_实例分析_顶点膨胀.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson14_表面着色器_实例分析_顶点膨胀 : MonoBehaviour
{
void Start()
{
#region 知识回顾 表面着色器中如何处理顶点?
//在编译指令中
//#pragma surface 表面函数名 光照模型 可选额外参数
//可选额外参数中添加
//vertex:自定义函数名
//函数格式:
//void 自定义函数名(inout appdata_full v)
#endregion
#region 知识点一 实现顶点膨胀效果
//直接在Lesson13实现法线贴图的代码中进行修改即可
//1.加入顶点碰撞控制参数
//2.在编译指令中加入顶点处理函数
//3.自定义顶点处理函数
//4.在该函数中对顶点进行偏移
#endregion
#region 知识点二 感受最终颜色处理函数
//可选额外参数中添加
//finalcolor:自定义函数名
//函数格式:
//void 自定义函数名(Input IN, SurfaceOutput... o, inout fixed4 color)
#endregion
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com