【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门

Unity Shader基本结构

Unity Shader简单结构

下面的Shader代码是一个比较基础的Shader的伪代码表示 :

Shader "Shader Name" {
    Properties {
        propertiesName1("display name1", PropertyTypeA) = DefaultValueA
        propertiesName2("display name2", PropertyTypeB) = DefaultValueB
    }
    SubShaderA {
        [Tags]
        [RenderSetup]
        
        Pass {
            CDPROGRAM
            #include "xxx.cginc"
            ENDCG
        }        
    }
    SubShaderB {
        //...
    }
    Fallback ""
}

 

UnityShader基本属性

Properties

Properties语义块支持的属性类型:

Shader "ShaderName" {
    Properties {
        _Int("Int", Int) = 2
        _Float("Float",Float) = 1.5
        _Range("Range", Range(0.0, 5.0)) = 3.0
        _Color("Color", Color) = (1, 1, 1, 1)
        _Vector("Vector", Vector) = (1, 1, 1, 1)
        // Textures
        _2D("2D", 2D) = ""{}
        _Cube("Cube", Cube) = "White"{}
        _3D("3D", 3D) = "black"{}
    }
}

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第1张图片

 

Pass

顶点着色器和片元着色器都写在Pass内,Pass定义了一次完整的渲染流程

Pass语义如下:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第2张图片

Pass里也包含了自己的标签,标签类型有:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第3张图片

SubShader

每个UnityShader文件可以包含多个SubShader,至少包含一个:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第4张图片

在SubShader中定义一系列Pass,以级可选的RederSetup和Tags。但Pass数目过多,往往会导致渲染性能的下降。

 

RenderSetup

常见的渲染状态设置指令:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第5张图片

如果在SubShader中设置了上述的渲染状态时,会应用的所有的Pass中。我们也可以在设置了这些状态时,如果希望在某个Pass中不使用该渲染指令,可以单独设置RenderSetup。

Fallback

紧跟在各个SubShader后面的是Fallback,它会告诉Unity,如果前面的SubShader不能在显卡上运行,则运行Fallback定义的最低级的Shader。

 

Shader示例

一个简单的Shader代码如下:

// shader名字
Shader "Unity ShaderTest/Simple Test Shader"{
	// SubShader使用默认渲染设置(RenderSetup)和标签设置(Tags)
	Properties {
		_Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
	}
	SubShader {
		Pass {
			CGPROGRAM

			#include "UnityCG.cginc"

			// #pragma vertex name  // name为函数名,告诉Unity这个函数包含了顶点着色器代码
			// #pragma fragment name  // name告诉Unity这个函数包含了片元着色器代码
			#pragma vertex vert
			#pragma fragment frag

			// 为了在CG代码中访问属性, 需要定义一个与属性名称和类型都匹配的变量
			fixed4 _Color;
			// application to vert
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};
			// vert to frag
			struct v2f {
				float4 pos : SV_POSITION;
				fixed3 color : COLOR0;
			};

			// 参数 包含了这个顶点的位置, 通过POSITION语义指定的
			v2f vert(a2v v) {
			    // mul 矩阵乘法 把顶点位置从模型空间转换到裁剪空间
				// return mul(UNITY_MATRIX_MVP, v.vertex);
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				// v.normal 包含了顶点的法线方向, 分量范围在[-1.0, 1.0]

				// 把范围映射到[0, 1.0]
				o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				//return fixed4(i.color, 1.0);
				fixed3 c = i.color;
				c *= _Color.rgb;
				return fixed4(c, 1.0);
			}
			ENDCG
		}
	}
}

从头到尾说。这里定义了一个名叫Simple Test Shader的shader,它的路径为Unity ShaderTest/Simple Test Shader,然后定义了一个名为_Color的Properties;
接下来就是主干部分SubShader了,里面直接是一个Pass内容,从Pass的代码里可以看到,我们顶点/片元着色器都是写在CGPROGRAM和ENDCG里的;
#include "UnityCG.cginc",表示我们使用了UnityShader的一个头文件,后缀名为.cginc,我们会用到里面的成型的API等;
#pragma vertex vert和#pragma fragment frag,表示我们告诉Unity,vert函数定义了顶点着色器的代码,frag定义了片元着色器的代码
fixed4 _Color; 为了在CG代码中访问属性, 我们需要定义一个与属性名称和类型都匹配的变量;
接下来,我们定义了两个struct,一个是从应用到顶点的结构体a2v,一个是从顶点到片元的结构体v2f,a2v会把从应用阶段的数据传送给顶点着色器,v2f会把顶点着色器计算后的值传给片元着色器;

最后,片元着色器的输出语义为SV_Target,它也是HLSL的一个系统语义,告诉渲染器,把用户的输出颜色存储到一个渲染目标中。

 

Shader语义等介绍

 

vert函数的输入a2v,内置了3个变量,其中vertex通过POSITION语义来告诉Unity,将模型的顶点坐标传到自己的空间里;normal表示模型空间的法线,通过NORMAL语义来指定;TEXCOORD0来告诉Unity,使用模型的第一套纹理来填充texcoord;

v2f作为顶点着色器的输出,它必须要包含的一个值,语义是SV_POSITION,它告诉Unity,顶点着色器的输出是裁剪空间中的坐标,否则片元着色器无法得知裁剪空间中的坐标值。

我们在这段Shader代码中用到了Color类型,它的变量类型是float4/half4/fixed4,类似的还有:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第6张图片

上图中看到了CG/HLSL中的3种精度数值类型,float/half/fixed:

我们在选择精度类型时,尽可能选用精度较低的类型。

Unity支持的语义:

1.从应用阶段传递模型数据给顶点着色器时Unity支持的常用语义:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第7张图片

上图里,TEXCOORDn,其中n的数目和ShaderModel有关,一般在ShaderModel2和3里,n等于8,而在4和5里,n等于16;

POSITION,TANGENT,NORMAL这些数据,在Unity中,它们是由使用该材质的MeshRender组件提供的,每帧进行DrawCall的时候,MeshRender都会负责把模型数据传递给UnityShader。
 

2. 从顶点着色器传递数据给片元着色器时Unity使用的常用语义

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第8张图片

 

3.片元着色器输出时常用的语义

 

UnityCG.cginc种一些常用的帮助函数:

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第9张图片

 

UnityShader内置的一些变量:

1.Unity内置的变换矩阵

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第10张图片

其中_World2Object(Unity5.5中已经更名为_unityWorldToObject),在光照部分里,法线和光源方向的计算中会用到,因为计算法线变换时,需要用到逆矩阵。

2. Unity内置的摄像机和屏幕参数

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第11张图片

【Unity Shader入门精要学习笔记】顶点&片元着色器上手和入门_第12张图片

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(UnityShader,3D计算机图形学&OpenGL)