本文是unity官方教程的着色器部分入门教程的翻译
本教程将教你怎么创建你自己的着色器,让你的游戏看起来更棒!
Unity装配有一整套强有力的材质着色语言ShaderLab。在风格上,它和CgFX、Direct3D Effects(.FX)语言很像-它们同样描述了显示一个材质所需的一切。
着色器描述了属性并都会显示在Unity的Material Inspector中,也描述了实现(SubShaders)在不同的图形硬件能力上使用的多重着色器,每个描述都用来完成图形硬件的渲染状态,固定函数管线的建立或者要去使用的顶点/片元程序。顶点和片元程序是用高水准的Cg/HLSL编程语言写的。
在本教程中我们将描述如何用固定函数和编程管线去写着色器。我们假定读者对OpenGL和Direct3D渲染状态、固定函数和编程管线有基本的了解,而且对编程语言Cq、HLSL和GLSL有一些认识。一些着色器教程和文档可以在NVIDIA和AMD开发者网站找到。
开始:
创建一个新的着色器,或者从菜单栏选择
<span style="font-size:18px;">Shader "Tutorial/Basic" {
Properties {
_Color ("Main Color", Color) = (1,0.5,0.5,1)
}
SubShader {
Pass {
Material {
Diffuse [_Color]
}
Lighting On
}
}
}
</span>
这个简单的着色器说明了大部分基本着色器所具有的形式。它定义了一个叫Main Color的颜色属性并分配给它一个默认的颜色值(red=100%green=50%blue=50%alpha=100%)。它通过引用一个pass来渲染物体,在这个pass中_Color属性设置有diffuse材质组件,打开了per-vertex光。
为了测试这个着色器,创建一个新的材质,从下来菜单(Tutorial->Basic)选择着色器,分配该材质到一些物体上。改变Material Inspector面板中的颜色值观看颜色变化。是时候尝试更复杂的东西了。
基本顶点灯光:
如果你打开一个已存在的复杂的着色器,它可能有一点难度去理解。为了更好的开始,我们将剖析Unity中内建的VertexLit着色器。这个着色器使用固定函数管线去实现逐顶点照明。
<span style="font-size:18px;">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
SeparateSpecular On
SetTexture [_MainTex] {
constantColor [_Color]
Combine texture * primary DOUBLE, texture * constant
}
}
}
}
</span>
所有的着色器都是以关键词Shader开始的,并且后面跟随一个用以标定该着色器名字的字符串。这个名字将会展示在Inspector中。所有的着色器代码都必须要放在Shader后面的花括号里面{}(叫做块)
- shader的名字需要简短、好描述,不必连着.shader文件名。
- 要把着色器放到Unity的子菜单中,使用slashes,例如:MyShaders/Test意思是Test是在子菜单MyShaders下,或者MyShaders->Test。
着色器是由跟随有SubShader块的Properties块组成的。它们都将在下面进行叙述。
属性:
你可以在着色器块的开始定义任何的属性以便于设计师可以在Matrial Inspector进行编辑。在VertexLit例子中属性类似:
这些属性被分别按行列在属性块内。每个属性都是以内建名字(Color,MainTex)开始的。在内建名字之后插入的是inspector中将要显示的名字和该属性的类型。之后是该属性的默认值:
这些可能的属性类型都在Properties Reference中。属性的默认值依赖于属性的类型。在这个例子中,属性类型是color,默认值需要是一个四值向量。
现在我们的属性已经定义好了,是时候写实际的着色器代码了。
着色器体:
在继续之前,先让我们来定义着色器文件的基本结构。
不同的图形硬件有不同的能力。例如,一些图形显卡支持片元程序,另外一些则不支持,一些图形硬件在pass中可以制定四张纹理,另外一些仅仅可以制定2张或者1张纹理,等等。为了让你更好的利用你用户的图形硬件,一个着色器可以包含多个SubShaders。当Unity渲染一个着色器时,它将逐个检查所有的subshaders,并将选择该图形硬件所支持的第一个subshader。
<span style="font-size:18px;">Shader "Structure Example" {
Properties { /* ...shader properties... }
SubShader {
// ...subshader that uses vertex/fragment programs...
}
SubShader {
// ...subshader that uses four textures per pass...
}
SubShader {
// ...subshader that uses two textures per pass...
}
SubShader {
// ...subshader that might look ugly but runs on anything :)
}
}</span>
系统允许Unity支持所有已存在的硬件而且最大化利用该硬件的性能。因为这个,导致了一些长的着色器。
在每一个SubShader块中可以设置所有通道中共享的渲染状态,定义它们自己的渲染通道。所有可用的命令可以再SubShader Reference中找到。
通道:
每一个subshader都是一系列通道的集合,对于每一个通道, 几何对象将被渲染,因此那里至少有一个通道。我们的VertexLit着色器只有一个通道:
<span style="font-size:18px;">// ...snip...
Pass {
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
Lighting On
SeparateSpecular On
SetTexture [_MainTex] {
constantColor [_Color]
Combine texture * primary DOUBLE, texture * constant
}
}
// ...snip...</span>
通道中定义的命令配置了使用何种方式用图形硬件去渲染几何物体。
在上面的例子中,我们有一个能绑定我们的属性到固定函数照明材质设置的材质块。Lighting On命令用来打开标准顶点照明,SeparateSpecular On允许使用高亮的单色镜面。
所有这些命令都非常快速直接的映射到OpenGL/Direct3D硬件模型的固定函数。可以查阅OpenGL red book看看更多内容。
下一个命令,SetTexture,非常重要,这些命令定义了我们在渲染中想去使用、混合、结合和应用的纹理。紧跟着SetTexture命令的是我们想使用(这里是_MainTex)的纹理的属性。后面跟着一个怎么应用该纹理的结合器块。在屏幕中渲染的每一个像素都会执行结合器中的命令。
我们在这个块内设置一些常量颜色值,也就是材质的颜色_Color。下面我们使用常量颜色:
我们将在下一个命令中指定怎么用颜色值去和纹理混合。我们用Combine命令指定怎么用另一个纹理或者颜色去和我们的纹理进行混合。通常就像:Combine ColorPart,AlphaPart。
ColorPart和AlphaPart分别定义了颜色组件(RGB)的混合和透明度组件(A)的混合。如果AlphaPart被省略了,它将会使用像ColorPart一样的混合。
在VertexLit例子中:Combine texture* primary DOUBLE,texture* constant
在这里,纹理就是来自当前纹理(这里指_MainTex)的颜色。它乘以(*)主要的顶点颜色。主要的颜色就是顶点照明颜色,也就是从上面的材质的值中计算而来的。最后,结果乘以2目的是增加光亮(DOUBLE)。透明度的值(逗号后面)就是纹理乘以常量值(上面设置的constantColor)。另一种经常使用的结合器模式叫做预览(本着色器不再使用)。这是所有之前SetTexture步骤的结果,可以被用于和一些纹理和/或颜色互相结合。
总结:
我们的VertexLit着色器配置标准的顶点照明并建立纹理装配器以便于渲染的灯光强度加倍。我们可以把更多的通道运用到着色器上,它们将会在别的后面渲染一个。现在,虽然,这是没有必要的,因为我们有了渴望的效果。我们只需要一个SubShader因为我们不使用任何先进的功能 - 这个特殊的着色器将工作在Unity支持的一起显卡上。我们可以认为VertexLit着色器是最基本的着色器之一。我们既不必为任何硬件指定特定的操作,也不用使用任何ShaderLab和Cg提供的特殊的和极少使用的命令。