西安商城网站开发,和wordpress类似的框架,一个完整网页的制作,wordpress程序备份一个最简单的顶点/片元着色器
一个最简单的顶点/片元着色器
Unity Shader的基本结构。它包含了Shader、Properties、SubShader、Fallback等语义块。顶点/片元着色器的结构与之大体类似 Shader MyShaderName {Properties {// 属性}SubShader {// 针对显卡A的S…一个最简单的顶点/片元着色器
一个最简单的顶点/片元着色器
Unity Shader的基本结构。它包含了Shader、Properties、SubShader、Fallback等语义块。顶点/片元着色器的结构与之大体类似 Shader MyShaderName {Properties {// 属性}SubShader {// 针对显卡A的SubShaderPass {// 设置渲染状态和标签// 开始CG代码片段CGPROGRAM// 该代码片段的编译指令例如#pragma vertex vert#pragma fragment frag// CG代码写在这里ENDCG// 其他设置}// 其他需要的Pass}SubShader {// 针对显卡B的SubShader}// 上述SubShader都失败后用于回调的Unity ShaderFallback VertexLit}
一个简单的代码
// Upgrade NOTE: replaced mul(UNITY_MATRIX_MVP,*) with UnityObjectToClipPos(*)Shader Unity Shaders Book/Chapter 5/Simple Shader {SubShader{Pass {CGPROGRAM#pragma vertex vert#pragma fragment fragfloat4 vert(float4 v : POSITION) : SV_POSITION {return UnityObjectToClipPos(v);}fixed4 frag() : SV_Target {return fixed4(1.0, 1.0, 1.0, 1.0);}ENDCG}}
}
效果 讲解
代码的第一行通过Shader语义定义了这个Unity Shader的名字——“Unity Shaders Book/Chapter 5/Simple Shader
Properties语义并不是必需的我们可以选择不声明任何材质属性
两条编译指令 #pragma vertex vert #pragma fragment frag 它们告诉Unity哪个函数包含了顶点着色器的代码哪个函数包含了片元着色器的代码
更一般的形式 #pragma vertex name #pragma fragment name //其中name 就是我们指定的函数名 float4 vert(float4 v : POSITION) : SV_POSITION {return mul (UNITY_MATRIX_MVP, v);}
这就是本例使用的顶点着色器代码它是逐顶点执行的。vert函数的输入v包含了这个顶点的位置这是通过POSITION语义指定的。它的返回值是一个float4类型的变量它是该顶点在裁剪空间中的位置POSITION和SV_POSITION都是CG/HLSL中的语义semantics它们是不可省略的这些语义将告诉系统用户需要哪些输入值以及用户的输出是什么
例如这里POSITION将告诉Unity把模型的顶点坐标填充到输入参数v中SV_POSITION将告诉Unity顶点着色器的输出是裁剪空间中的顶点坐标
return 执行的代码的意思是把顶点坐标从模型空间转换到裁剪空间中。UNITY_MATRIX_MVP矩阵是Unity内置的模型·观察·投影矩阵 fixed4 frag() : SV_Target {return fixed4(1.0, 1.0, 1.0, 1.0);}
在本例中frag函数没有任何输入。它的输出是一个fixed4类型的变量并且使用了SV_Target语义进行限定。SV_Target也是HLSL中的一个系统语义它等同于告诉渲染器把用户的输出颜色存储到一个渲染目标render target中这里将输出到默认的帧缓存中。片元着色器中的代码很简单返回了一个表示白色的fixed4类型的变量。片元着色器输出的颜色的每个分量范围在[0, 1]其中(0, 0,0)表示黑色而(1, 1, 1)表示白色。
模型数据从哪里来 为了自建一个自定义的结构体我们必须使用如下格式来定义它 struct StructName {Type Name : Semantic;Type Name : Semantic;.......};
其中语义是不可以被省略的
我们修改了vert函数的输入参数类型把它设置为我们新定义的结构体a2v。通过这种自定义结构体的方式我们就可以在顶点着色器中访问模型数据。
在Unity中填充到POSITION, TANGENT, NORMAL这些语义中的数据是由使用该材质的Mesh Render组件提供的。在每帧调用Draw Call的时候Mesh Render组件会把它负责渲染的模型数据发送给Unity Shader
我们知道一个模型通常包含了一组三角面片每个三角面片由3个顶点构成而每个顶点又包含了一些数据例如顶点位置、法线、切线、纹理坐标、顶点颜色等
顶点着色器和片元着色器之间如何通信
顶点着色器是逐顶点调用的而片元着色器是逐片元调用的。片元着色器中的输入实际上是把顶点着色器的输出进行插值后得到的结果。 Shader Unity Shaders Book/Chapter 5/Simple Shader {SubShader {Pass {CGPROGRAM#pragma vertex vert#pragma fragment fragstruct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};// 使用一个结构体来定义顶点着色器的输出struct v2f {// SV_POSITION语义告诉Unity, pos里包含了顶点在裁剪空间中的位置信息float4 pos : SV_POSITION;// COLOR0语义可以用于存储颜色信息fixed3 color : COLOR0;};v2f vert(a2v v) : SV_POSITION {// 声明输出结构v2f o;o.pos mul(UNITY_MATRIX_MVP, v.vertex);// v.normal包含了顶点的法线方向其分量范围在[-1.0, 1.0]// 下面的代码把分量范围映射到了[0.0, 1.0]// 存储到o.color中传递给片元着色器o.color v.normal 0.5 fixed3(0.5, 0.5, 0.5);return o;}fixed4 frag(v2f i) : SV_Target {// 将插值后的i.color显示到屏幕上return fixed4(i.color, 1.0);}ENDCG}}}
在上面的代码中我们声明了一个新的结构体v2f。v2f用于在顶点着色器和片元着色器之间传递信息。同样的v2f中也需要指定每个变量的语义。在本例中我们使用了SV_POSITION和COLOR0语义。顶点着色器的输出结构中必须包含一个变量它的语义是SV_POSITION。否则渲染器将无法得到裁剪空间中的顶点坐标也就无法把顶点渲染到屏幕上。COLOR0语义中的数据则可以由用户自行定义但一般都是存储颜色例如逐顶点的漫反射颜色或逐顶点的高光反射颜色
如何使用属性 Shader Unity Shaders Book/Chapter 5/Simple Shader {Properties {// 声明一个Color类型的属性_Color (Color Tint, Color) (1.0,1.0,1.0,1.0)}SubShader {Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag// 在CG代码中我们需要定义一个与属性名称和类型都匹配的变量fixed4 _Color;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;fixed3 color : COLOR0;};v2f vert(a2v v) : SV_POSITION {v2f o;o.pos mul(UNITY_MATRIX_MVP, v.vertex);o.color v.normal 0.5 fixed3(0.5, 0.5, 0.5);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 c i.color;// 使用_Color属性来控制输出颜色c _Color.rgb;return fixed4(c, 1.0);}ENDCG}}}
在上面的代码中我们首先添加了Properties语义块中并在其中声明了一个属性_Color它的类型是Color初始值是(1.0,1.0,1.0,1.0)对应白色。为了在CG代码中可以访问它我们还需要在CG代码片段中提前定义一个新的变量这个变量的名称和类型必须与Properties语义块中的属性定义相匹配。 强大的援手Unity提供的内置文件和变量