文章目录
- 前言
- 一、片元漫反射着色器是什么?
- 1. 片元漫反射着色器的工作原理
- 2. 顶点漫反射着色器和片元漫反射着色器的比较
- 顶点漫反射着色器
- 优点:
- 缺点:
- 片元漫反射着色器
- 优点:
- 缺点:
- 二、使用步骤
- 1. Shader 属性定义
- 2. SubShader 设置
- 3. 渲染 Pass
- 4. 定义结构体和顶点着色器函数
- 5. 片元着色器函数
- 三、效果
- 四、总结
前言
在 Unity 中,Shader 可以用来实现各种视觉效果。本教程将详细介绍如何编写一个基于片元漫反射的着色器,使物体的颜色根据光照和法线方向的变化而变化。
一、片元漫反射着色器是什么?
1. 片元漫反射着色器的工作原理
片元漫反射着色器(Fragment Diffuse Shader)是一种用于在渲染过程中模拟物体表面的漫反射光照效果的着色器。它在每个像素(片元)级别计算光照效果,根据光源的位置和物体表面的法线方向来确定像素的颜色值。片元漫反射着色器通常用于创建逼真的光照效果,使物体的表面在不同的光照条件下呈现出合适的明暗和颜色变化。
2. 顶点漫反射着色器和片元漫反射着色器的比较
顶点漫反射着色器
工作原理:在顶点级别计算光照效果,将结果传递到片元着色器进行渲染。
优点:
计算开销相对较低,适用于大型场景或性能受限环境。
具有较好的性能表现,尤其在移动设备上。
缺点:
光照效果相对简单,可能缺乏真实感。
可能无法准确地模拟一些复杂的光照场景,如阴影和反射。
片元漫反射着色器
工作原理:在每个像素(片元)级别计算光照效果,直接在片元着色器中进行光照计算。
优点:
能够更准确地模拟光照效果,包括阴影和反射等。
提供更高的视觉真实感,可以产生更细致的光照效果。
缺点:
计算开销较大,可能影响性能,特别是在复杂场景中或移动设备上。
可能需要更多的计算资源,不适用于性能要求较高的应用场景。
二、使用步骤
1. Shader 属性定义
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1) // 漫反射颜色属性,默认白色
}
这段代码定义了 Shader 的属性。在本例中,我们只有一个属性 _Diffuse,表示物体的基本颜色,使用 RGBA 形式表示。默认为白色。
2. SubShader 设置
SubShader
{
Tags
{
"RenderType" = "Opaque" // 渲染类型为不透明
}
LOD 100 // 细节级别
}
SubShader 定义了一组渲染设置,包括标签和细节级别。在这里,我们将渲染类型标签设置为 “Opaque”,表示物体是不透明的。
3. 渲染 Pass
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
}
这里开始了渲染 Pass 部分。在这里,我们使用了 CGPROGRAM 指令来声明顶点着色器和片元着色器函数。#pragma vertex vert 和 #pragma fragment frag 分别指定了顶点着色器函数和片元着色器函数的名称。
然后,我们包含了 UnityCG.cginc 和 Lighting.cginc,它们提供了许多有用的函数和宏,用于简化编写 Shader。
4. 定义结构体和顶点着色器函数
struct v2f
{
float4 vertex : SV_POSITION; // 顶点位置
fixed3 worldNormal : TEXCOORD0; // 颜色
};
v2f vert(appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // 顶点位置变换到裁剪空间
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); // 世界空间法线
o.worldNormal = worldNormal;
return o;
}
这里定义了结构体 v2f,用于从顶点着色器向片元着色器传递数据。在顶点着色器函数中,我们将顶点位置转换到裁剪空间,并计算世界空间的法线向量。
5. 片元着色器函数
fixed4 frag(v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //获取环境光
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz); //获取光源位置
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldLight, i.worldNormal)); // 计算漫反射
fixed3 color = diffuse + ambient; // 最终颜色
return fixed4(color, 1); // 输出颜色
}
片元着色器函数计算最终的颜色。首先,我们获取环境光和光源位置。然后,计算漫反射光照,并将环境光和漫反射光照相加得到最终颜色。
三、效果
顶点漫反射效果
片元漫反射效果
左:顶点漫反射 右:片元漫反射
四、总结
片元漫反射和顶点漫反射都是用于模拟物体在光照条件下的表现的重要技术。
片元漫反射提供了更精细的光照效果,适用于需要高度真实感和精细光照效果的场景;而顶点漫反射则适用于对性能要求较高的场景或需要大量物体渲染的场景。
在实际应用中,根据需求和场景的不同,可以选择合适的着色器技术来实现所需的光照效果。