Unity3D Shader学习之六—顶点和片段着色器
基于上一篇文章的内容,将重点放在顶点和片段着色器。 下面是顶点和片段着色器的基本结构:
//着色器的名称,将出现在编辑器中所列出的材质检视器列表中
Shader "MyShaderName" {
//着色器可以有一系列属性。着色器中定义的任何属性都显示在 Unity 内的材质检视器中。典型属性有物体颜色和纹理,或者只是着色器使用的任意值。
Properties {
// ... properties here ...
}
//数目不定,但至少要有一个,Unity会选择最适合的SubShader运行到指定平台
SubShader {
// ... subshader for graphics hardware A ...
//数据不定,但至少要有一个,通道 (Pass) 块使对象的几何结构被渲染一次
Pass {
// ... pass commands ...
}
// ... more passes if needed ...
}
SubShader {
// ... subshader for graphics hardware B ...
}
// ... Optional fallback ...
//如果所有子着色器都无法在该硬件上运行,就运行此着色器,异常处理
FallBack "VertexLit"
}
各部分详细说明: Name: Shader “name“ { [Properties] Subshaders [Fallback] } 定义一个着色器 可以支持/,在编辑中以目录的形式展示,例如:
Shader “Test/ShaderTest” {}
Properties: 属性 (Properties) { Property [_Property …_] }定义属性块。括号内,多个属性定义如下。
* _name_ ("_display name_", **Range** (_min_, _max_)) = _number_定义浮点属性,代表检视器中从_最小值 (min)_ 到_最大值 (max)_的滑块。
* _name_ ("_display name_", **Color**) = (_number_,_number_,_number_,_number_)定义颜色属性。
* _name_ ("_display name_", **2D**) = "_name_" { _options_ }定义二维纹理属性。
* _name_ ("_display name_", **Rect**) = "_name_" { _options_ }定义矩形(非 2 的幂)纹理属性。
* _name_ ("_display name_", **Cube**) = "_name_" { _options_ }定义立方体贴图纹理属性。
* _name_ ("_display name_", **Float**) = _number_定义浮点属性。
* _name_ ("_display name_", **Vector**) = (_number_,_number_,_number_,_number_)定义四分量向量属性。
如果您想在着色器程序中访问那些属性中的一些属性,您需要声明一个具有相同名称和匹配类型的 Cg/HLSL 变量。例如,以下这些着色器属性:
_MyColor ("Some Color", Color) = (1,1,1,1)
_MyVector ("Some Vector", Vector) = (0,0,0,0)
_MyFloat ("My float", Float) = 0.5
_MyTexture ("Texture", 2D) = "white" {}
_MyCubemap ("Cubemap", CUBE) = "" {}
将在 Cg/HLSL 代码中被声明为:
fixed4 _MyColor; // 精度低的类型对颜色来说已足够
float4 _MyVector;
float _MyFloat;
sampler2D _MyTexture;
samplerCUBE _MyCubemap;
SubShader: Subshader **{** \[_Tags_\] \[_CommonState_\] _Passdef_ \[_Passdef ..._\] **}**定义子着色器为可选的标记、普通状态和一系列通道定义。 Pass: Pass **{** _\[Name and Tags\] \[RenderSetup\] \[TextureSetup\]_ **}**基本通道命令包含了渲染设置命令的可选列表,后面可跟随一系列纹理以供使用。 Pass结构是这样的,Cg 程序代码片段被编写在 _CGPROGRAM_ 和 _ENDCG_ 之间。
Pass {
// ...常用的通道状态设置...
CGPROGRAM
// 该代码片段的编译指令,例如:
#pragma vertex vert
#pragma fragment frag
// Cg 代码自身
ENDCG
// ...通道设置的剩余部分...
}
FallBack: Fallback”name”回退到有给定名称的着色器。 Fallback Off 回退关闭,明确表示即使没有子着色器可以在该硬件上运行,也不会有回退以及应打印的警告。 顶点着色器示例:
Shader "VertexInputSimple" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
//vertex to fragment
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
//appdata_base 包含application to vertex参数
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY\_MATRIX\_MVP, v.vertex);
o.color.xyz = v.normal * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
//
fixed4 frag (v2f i) : COLOR0 { return i.color; }
ENDCG
}
}
}
看示例中的蓝色部分: 1.#pragma vertex vert #pragma指令,指定vertex函数为vert,常用的指令有:
* #pragma vertex _名称_ \- 将函数_名称_编译为顶点着色器。
* #pragma fragment _名称_ \- 将函数_名称_编译为片元着色器。
* #pragma geometry _名称_ \- 将函数_名称_编译为 DX10 几何结构着色器。要使这个选项自动打开 #pragma target 4.0
* #pragma hull _名称_ \- 将函数_名称_编译为 DX11 外壳着色器。要使这个选项自动打开 #pragma target 5.0
* #pragma domain _名称_ \- 将函数_名称_编译为 DX11 域着色器。要使这个选项自动打开 #pragma target 5.0
2.#include “UnityCG.cginc” Unity可包含引入预定义变量和帮助函数的文件,其他内置文件有:
* `HLSLSupport.cginc`\- (自动包含) 用于跨平台着色器编译的帮助宏和定义。
* `UnityCG.cginc`\- 常用的全局变量和帮助函数。
* `AutoLight.cginc`\- 光照和阴影功能,例如,表面着色器在内部使用此文件。
* `Lighting.cginc`\- 标准表面着色器光照模型;当您编写表面着色器时自动将其包含。
* `TerrainEngine.cginc`\- 用于地形 (Terrain) 和植被 (Vegetation) 着色器的帮助函数。
3.appdata_base 是一个数据结构,提供顶点数据给 Cg/HLSL 顶点程序,几个常用的顶点结构定义在UnityCG.cginc 包含文件,大多数情况下只使用它们就足够了。其它结构有:
* appdata_base: 顶点由位置、法线和一个纹理坐标构成。
* appdata_tan: 顶点由位置、切线、法线和一个纹理坐标构成。
* appdata_full: 顶点由位置、切线、法线、两个纹理坐标以及颜色构成
结构成员必须是下面列出的成员: float4 vertex 是顶点位置 float3 normal 是顶点法线 float4 texcoord 是第一个 UV 坐标 float4 texcoord1 是第二个 UV 坐标 float4 tangent 是切线向量(用于法线贴图) float4 color 是逐顶点颜色
顶点着色器是如何知道这些成员的含义的呢?是由成员定义时后跟冒号加字符串指定的!这些字符串就是语义。例如appdata_base定义如下(请查看UnityCG.cginc源文件):
struct appdata_full {
float4 vertex : POSITION;//模型空间的顶点位置
float4 tangent : TANGENT;//模型空间的顶点切线
float3 normal : NORMAL;//模型空间的顶点法线
float4 texcoord : TEXCOORD0;//顶点的第一组纹理坐标
float4 texcoord1 : TEXCOORD1;//顶点的第2组纹理坐标
float4 texcoord2 : TEXCOORD2;//顶点的第3组纹理坐标
float4 texcoord3 : TEXCOORD3;//顶点的第4组纹理坐标
#if defined(SHADER\_API\_XBOX360)
half4 texcoord4 : TEXCOORD4;//顶点的第5组纹理坐标
half4 texcoord5 : TEXCOORD5;//顶点的第6组纹理坐标
#endif
fixed4 color : COLOR;//顶点颜色
};
4.SV_POSITION,COLOR0 上面提到了语义,SV_POSITION也是语义。但这个是顶点到片段着色器的语义。顶点到片段着色器的语义列表:
SV_POSITION:裁剪空间坐标,必须包含
COLOR0:输出第一组顶点颜色,可选
COLOR1:输出的第二组颜色,可选
TEXCOORD0-TEXCOORD7:输出纹理坐标,可选
5.UNITY_MATRIX_MVP Unity 内置的空间变换矩阵,位于HLSLSupport.cginc,上面提到了是自动包含的,所以着色器可以直接使用。其他变换矩阵及其含义,在下一篇会详细介绍! 要想了解每个部分的详细含义及内容,请查看官方文档。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 xue_huashan@163.com
文章标题:Unity3D Shader学习之六—顶点和片段着色器
文章字数:1.7k
本文作者:max-xue
发布时间:2016-10-31, 17:05:47
最后更新:2019-11-09, 22:31:50
原始链接:http://blog.le-more.com/2016/10/31/u3d/unity3d-shader-e5-ad-a6-e11/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。