u3d特效基础教程

2015年02月27日 12:08 0 点赞 0 评论 更新于 2025-11-21 16:31

本教程将指导你如何创建自己的着色器(Shaders),让你的游戏场景呈现出更出色的视觉效果。Unity 配备了强大的阴影和材质语言工具——ShaderLab。从编程语言的角度来看,它的语法类似于 CgFX 和 Direct3D。ShaderLab 不仅记录基本的顶点(vertex)或像素(pixel)信息,还描述了材质所需的所有信息。

一、Shaders 概述

1.1 Shaders 的性质与描述

在 Unity 材质检视器中,可以查看 Shaders 的性质以及多重子着色器(SubShaders)的描述。针对不同的图形硬件,每个描述都详细说明了图形硬件的渲染状态,包括固定功能管线(fixed function pipeline)的设置方式以及顶点/片段程序(vertex/fragment programs)的作用机制。顶点和片段程序可以使用高阶 Cg 编程语言或低阶着色器组合来实现。

1.2 前置知识

在本教程中,我们将介绍如何使用固定功能(fixed function)和可编程管线(programmable pipelines)两种方式在 ShaderLab 中编写着色器。假设读者具备基本的 OpenGL 或 Direct3D 渲染概念,了解固定功能和可编程管线的常识,掌握 HLSL 或 GLSL 编程语言技术。一些 Shader 教程与参考文件可在 NVIDIA 以及 AMD 的开发站上获取。

二、创建新的 Shader

创建新的 Shader 有两种方法:

  • 可以通过菜单 Assets -> Create -> Shader 来创建。
  • 也可以复制一个现有的 Shader 并进行编辑。新的 Shader 可以通过双击来启动编辑画面(UniSciTE)。

三、基础 Shader 范例

3.1 范例代码

Shader "Tutorial/Basic" {
Properties {
_Color ("Main Color", Color) = (1,0.5,0.5,1)
}
SubShader {
Pass {
Material {
Diffuse [_Color]
}
Lighting On
}
}
}

3.2 范例解释

这个 Shader 范例是众多 Shader 中最基础的一个。它定义了一个名为 Main Color 的颜色属性,并指定了玫瑰色的效果(红色 = 100%,绿色 = 50%,蓝色 = 50%,透明度 = 100%)。在调用时,会跳过漫反射材质的设置(_Color)并开启顶点光源。

3.3 测试方法

要测试这个 Shader,你可以创建一个新的材质,在 Shader 下拉菜单中选择 Tutorial -> Basic,然后将这个新材质指定到对象上。通过拖动材质检视器的颜色表,观察对象的颜色变化。

四、深入了解 Unity 内建的 VertexLit Shader

4.1 VertexLit Shader 代码

Shader "VertexLit" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0.5)
_SpecColor ("Spec Color", Color) = (1,1,1,1)
_Emission ("Emmisive Color", Color) = (0,0,0,0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" { }
}
SubShader {
Pass {
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
Lighting On
SeperateSpecular On
SetTexture [_MainTex] {
constantColor [_Color]
Combine texture * primary DOUBLE, texture * constant
}
}
}
}

4.2 Shader 结构说明

  • Shader 名称:所有的 Shaders 都必须以 Shader 关键字开头,接着是 Shader 的名称(例如:VertexLit),该名称将显示在检视器(Inspector)中。所有的语法都必须放在 { } 之内。如果要将 Shaders 放在 Unity 的子菜单下,可以使用斜线,例如:MyShaders/Test,在检视器中会看到一个名为 MyShaders 的子菜单,下面有一个名为 Test 的 Shader。
  • Properties 块:位于 Shader 块的起始位置,用于定义各种属性。这些属性可以在材质检视器中进行编辑。在 VertexLit 范例中,Properties 块的语法是单行的,每个属性描述由内部名称开始(例如:_Color_MainTex),括号中显示的名称也会显示在检视器上,之后描述的是该属性的默认值。可用的属性类型请参考 Properties Reference。默认值与属性类型有关,以颜色属性为例,默认值应由四个值组成。
  • SubShader 块:由于不同的绘图卡具有不同的能力,为了满足所有用户的硬件需求,一个 Shader 可以包含多个 SubShaders。当 Unity 计算 Shader 时,会详细检查所有的 SubShaders,并使用硬件支持的第一个。每个 SubShader 相当于一个途径集,对几何对象进行渲染至少需要一个途径。完整的 SubShader 语法请参照 SubShader Reference 章节。
  • Pass 块:定义了渲染的具体步骤。在 VertexLit Shader 中,Pass 块内的 Material 块定义了照明所需的几个固定参数,Lighting On 用于开启照明设备,SeperateSpecular On 则启用独立的镜面反射效果。这些命令都属于支持 OpenGL/Direct3D 技术的硬件本身可使用的固定功能,更多相关资料可参考 OpenGL 红皮书。
  • SetTexture 命令:这是一个非常重要的命令,用于定义影像纹理的混合、组合方式以及如何应用于渲染环境。SetTexture 通常跟随纹理的属性名称之后(这里使用 _MainTex),接下来的组合块(combiner block)定义了纹理的应用方式,其命令会在屏幕上显示每个被执行的动作。

五、Shader 的其他重要命令

5.1 FallBack 命令

FallBack "VertexLit"

回退命令用于在当前着色器没有 SubShaders 可以在用户的图形硬件上运行时,指定应该使用的着色器。其效果相当于在当前着色器的末尾包含后备着色器的所有 SubShaders。例如,如果你编写了一个凹凸映射着色器,但没有为老显卡编写一个非常基本的非凹凸映射版本,就可以回退到内置的 VertexLit 着色器。

5.2 UsePass 命令

UsePass "Specular/BASE"

该命令用于重用其他着色器中定义的途径代码。例如,上述命令使用了内置镜面着色器中名为 BASE 的途径。

5.3 Name 命令

Name "MyPassName"

通过 Name 命令可以为途径指定一个名称,以便在使用 UsePass 命令时引用。

六、顶点和片段程序

6.1 可编程管线与固定功能管线

当使用顶点和片段程序(即“可编程管线”)时,图形硬件中的大部分硬编码功能(“固定功能管线”)将被关闭。例如,使用顶点程序会完全关闭标准 3D 变换、灯光和纹理坐标生成;使用片段程序会替换 SetTexture 命令中定义的纹理组合模式,因此 SetTexture 命令不再必要。

6.2 编写顶点/片段程序

编写顶点/片段程序需要对三维转换、照明和坐标空间有透彻的理解,因为你必须自己重写类似于 OpenGL API 的固定功能。但另一方面,你可以实现比内置功能更多的效果。

6.3 在 ShaderLab 中使用 Cg 语言

在 ShaderLab 中,着色器通常使用 Cg 语言嵌入到“Cg 的片段着色器文本”中。Cg 片段会被编译成低级的统一着色器汇编代码,最终着色器文件只包含这个低层次的汇编代码。当选择一个项目视图中的着色器时,检查员会显示编译后的 Cg 语言文本,这有助于调试。Unity 会自动编译 Cg 片段以支持 OpenGL 和 Direct3D,所以你的着色器使用 Cg 语言都能正常工作。需要注意的是,由于 Cg 代码是由编辑器编译的,你不能在运行时通过脚本创建 Cg 着色器。

6.4 Cg 片段示例

Pass {
// ... 常规的途径状态设置 ...
CGPROGRAM
// 编译指令
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
// Cg 代码本身
#include "UnityCG.cginc"
struct v2f {
V2F_POS_FOG;
float3 color : COLOR0;
};
v2f vert (appdata_base v) {
v2f o;
PositionFog( v.vertex, o.pos, o.fog );
o.color = v.normal * 0.5 + 0.5;
return o;
}
half4 frag (v2f i) : COLOR {
return half4( i.color, 1 );
}
ENDCG
// ... 途径设置的其余部分 ...
}

6.5 示例解释

这个示例展示了一个使用 Cg 语言的着色器,它将对象的法线可视化。整个 Cg 片段写在 CGPROGRAMENDCG 关键字之间。开始的编译指令 #pragma 告诉编译器代码中包含的顶点程序和片段程序的函数名,以及为 OpenGL 片段程序添加的选项。接着,包含了一个内置的 Cg 文件 UnityCG.cginc,该文件包含常用的声明和函数,可使着色器代码更简洁。然后定义了一个 v2f 结构体,用于传递顶点程序到片段程序的信息。顶点程序 vert 计算法线颜色并进行缩放和偏移,片段程序 frag 则将计算得到的颜色作为输出。

6.6 使用着色器属性

当定义着色器属性时,会给它们一个名称,如 _Color_MainTex。在 Cg 语言中使用这些属性,只需定义一个匹配名称和类型的变量,Unity 会自动将 Cg 变量的名称与着色器属性进行匹配。以下是一个完整的着色器示例,展示了如何使用颜色调制纹理:

Shader "Tutorial/Textured Colored" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0.5)
_MainTex ("Texture", 2D) = "white" { }
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
#include "UnityCG.cginc"
float4 _Color;
sampler2D _MainTex;
struct v2f {
V2F_POS_FOG;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_base v) {
v2f o;
PositionFog( v.vertex, o.pos, o.fog );
o.uv = TRANSFORM_UV(0);
return o;
}
half4 frag (v2f i) : COLOR {
half4 texcol = tex2D( _MainTex, i.uv );
return texcol * _Color;
}
ENDCG
}
}
Fallback "VertexLit"
}

在这个示例中,定义了两个属性 _Color_MainTex,在 Cg 代码中定义了相应的变量。顶点程序使用 TRANSFORM_UV 宏确保纹理的缩放和偏移正确应用,片段程序对纹理进行采样并与颜色属性相乘。由于使用了自己编写的片段程序,不再需要 SetTexture 命令,片段程序可以完全控制纹理的着色方式。

七、总结

本教程展示了如何通过几个简单的步骤创建定制的着色器程序。虽然示例简单,但你可以编写任意复杂的着色器程序,充分发挥 Unity 的功能,实现最佳的渲染效果。完整的 ShaderLab 参考手册可在相关文档中找到。此外,在 forum.unity3d.com 论坛上也有关于着色器的讨论,你可以在那里获取帮助。祝你编程愉快,尽情享受 Unity 和 ShaderLab 的强大功能!

作者信息

boke

boke

共发布了 3994 篇文章