五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

UnityShader系列之2:入門篇

2018-11-24 18:11 作者:皮皮關(guān)做游戲  | 我要投稿

作者:朔宇


大家好。

吃飽喝足了之后才想起咱們還有這個(gè)系列需要填。

咳咳。之前的文章中,我們了解了渲染流水線及UnityShader的基本原理。這里放個(gè)上一期的傳送門:UnityShader系列之1:基礎(chǔ)篇


今天我們來具體了解UnityShader及ShaderLab。

ShaderLab

學(xué)習(xí)UnityShader首先要了解ShaderLab。

在Unity中,所有的UnityShader都是使用ShaderLab來編寫的,ShaderLab是Unity提供,用于編寫UnityShader的一種說明性語言,其用來描述一個(gè)UnityShader文件的結(jié)構(gòu)。我們先來看看ShaderLab的寫法:


Shader "ShaerName"{//UnityShader名稱

???????? Properties{

?????????????????? //屬性

???????? }

???????? SubShader {

?????????????????? //顯卡A使用的子著色器

???????? }

???????? SubShader {

?????????????????? //顯卡B使用的子著色器

???????? }

???????? FallBack "VertexLit"

}

?

在這個(gè)結(jié)構(gòu)中包含了許多渲染所需的數(shù)據(jù),如使用“Properties”定義著色器所需的各種屬性,這些屬性會(huì)在材質(zhì)面板中顯示。 Unity會(huì)根據(jù)使用的平臺(tái),來把這些結(jié)構(gòu)編譯成實(shí)際的代碼和Shader文件。 我們來詳細(xì)的分析上述偽代碼的語義含義和用途

1.第一行是定義UnityShader的名稱,定義了其名稱后我們就可以在使用此Shader的材質(zhì)選擇中找到這個(gè)名稱。

2.Properties中包含了一系列的屬性,這些屬性也將會(huì)在材質(zhì)面板中體現(xiàn),申明這些屬性可以更方便的在材質(zhì)面板中調(diào)整材質(zhì)的屬性。

3.SubShader,每一個(gè)UnityShader文件可以包含多個(gè)SubShader語義塊,但最少需要一個(gè)。當(dāng)Unity需要加在此Shader時(shí),Unity會(huì)掃描所有的SubShader,然后依次調(diào)用直到找到能夠在目標(biāo)平臺(tái)上運(yùn)行的SubShader。如果沒有,Unity就會(huì)使用Fallback語義制定的UnityShader。

UnityShader

接下來我們通過一個(gè)Unity默認(rèn)的頂點(diǎn)/片元著色器代碼來進(jìn)一步了解UnityShader。

在如下UnityShader中,我寫了關(guān)鍵位置的注釋,讀者可以對(duì)照閱讀從而進(jìn)一步了解UnityShader

//Shader名稱

Shader "Hidden/NewImageEffectShader"

{

???????? //申明所需的屬性

???????? Properties

???????? {

??????? //屬性名為_MainTex,面板所顯示的名稱為Texture,2D只屬性的類型

??????? //"white" 屬性默認(rèn)值

?????????????????? _MainTex ("Texture", 2D) = "white" {}

???????? }

???????? //一個(gè)Shader程序至少有一個(gè)SubShader,系統(tǒng)在渲染時(shí)會(huì)依次調(diào)用,直到找到匹配的SubShader,否則使用最后默認(rèn)指定的Shader

???????? SubShader

???????? {

?????????????????? //Cull Off:關(guān)閉陰影剔除

?????????????????? //ZWrite :將像素的深度寫入深度緩存中??

??????? //Always:將當(dāng)前深度值寫到顏色緩沖中

?????????????????? Cull Off ZWrite Off ZTest Always

?

?????????????????? //渲染通道

?????????????????? Pass

?????????????????? {

??????????????????????????? //Shader代碼段開始,著色器的代碼需要定義在CGPROGRAM-ENDCG之間

??????????????????????????? CGPROGRAM

??????????????????????????? //指定頂點(diǎn)著色器

??????????????????????????? #pragma vertex vert

??????????????????????????? //指定片元著色器

??????????????????????????? #pragma fragment frag

??????????????????????????? //引入U(xiǎn)nity內(nèi)置定義

??????????????????????????? #include "UnityCG.cginc"

?

??????????????????????????? //定義頂點(diǎn)著色器輸入結(jié)構(gòu)體

??????????????????????????? struct appdata

??????????????????????????? {

???????????????????????????????????? //float4是思維向量,這里相當(dāng)于告訴渲染引擎,這個(gè)屬性代表的含義

???????????????????????????????????? float4 vertex : POSITION;

???????????????????????????????????? //紋理

???????????????????????????????????? float2 uv : TEXCOORD0;

??????????????????????????? };

?

??????????????????????????? //與上邊類似,這里使用一個(gè)結(jié)構(gòu)體來定義頂點(diǎn)著色器的輸出

??????????????????????????? struct v2f

??????????????????????????? {

???????????????????????????????????? float2 uv : TEXCOORD0;

???????????????????????????????????? float4 vertex : SV_POSITION;

??????????????????????????? };

?

??????????????????????????? //Vertex 頂點(diǎn)函數(shù)實(shí)現(xiàn)

??????????????????????????? v2f vert (appdata v)

??????????????????????????? {

???????????????????????????????????? v2f o;

???????????????????????????????????? //傳遞進(jìn)來的頂點(diǎn)坐標(biāo)是模型坐標(biāo)系中的坐標(biāo)值,需要經(jīng)過矩陣轉(zhuǎn)換車成屏幕坐標(biāo)

???????????????????????????????????? o.vertex = UnityObjectToClipPos(v.vertex);

???????????????????????????????????? o.uv = v.uv;

???????????????????????????????????? //將計(jì)算后的結(jié)果輸出給渲染引擎,底層會(huì)根據(jù)具體的語義去做對(duì)應(yīng)的處理

???????????????????????????????????? return o;

??????????????????????????? }

???????????????????????????

??????????????????????????? sampler2D _MainTex;

?

??????????????????????????? //fragment 片元函數(shù)實(shí)現(xiàn)

??????????????????????????? fixed4 frag (v2f i) : SV_Target

??????????????????????????? {

???????????????????????????????????? fixed4 col = tex2D(_MainTex, i.uv);

???????????????????????????????????? col.rgb = 1 - col.rgb;

???????????????????????????????????? return col;

?????????????????? ???????? }

??????????????????????????? ENDCG

?????????????????? }

???????? }

}

?

我們通過一個(gè)實(shí)際的例子來看看UnityShader在實(shí)際項(xiàng)目中如何使用,這里我通過UnityShader來實(shí)現(xiàn)漫反射。

漫反射,是投射在粗糙表面上的光向各個(gè) 方向反射的現(xiàn)象。當(dāng)一束平行的入射光線射到粗糙的表面時(shí),表面會(huì)把光線向著四面八方反射,所以入射線雖然互相平行 ,由于各點(diǎn)的法線方向不一致,造成反射光線向不同的方向無規(guī)則地反射,這種反射稱之為“漫反射”或“ 漫射 ”。這種反射的光稱為漫射光。
漫反射光照是用于對(duì)那些被物體表面隨機(jī)散射到各個(gè)方向的輻射度進(jìn)行建模的。在漫反射中,視角的位置是不重要的因?yàn)槁瓷涫峭耆S機(jī)的,因此可以認(rèn)為在任何反射方向上的分布都是一樣的。但是入射光線的角度很重要。
漫反射符合蘭伯特定律(Lambert’s law):反射光線的強(qiáng)度與表面法線和光源方向之間夾角的余弦值成正比,因此,漫反射的計(jì)算如下:(C-light · M-diffuse)max(0,n·I)即光照顏色 漫反射顏色 max(0,法向量光照方向)
使用Lambert進(jìn)行漫反射渲染,在Shader中有兩種寫法,一種是逐頂點(diǎn)著色,另一種是逐像素著色

使用蘭伯特定律進(jìn)行漫反射渲染,在UnityShader中有兩種寫法,一種是逐頂點(diǎn)著色,另一種是逐像素著色。首先是逐頂點(diǎn):


Shader "AlbertShader/VertexDiffuse"

{

??? Properties

??? {

??????? //漫反射顏色初始為白色

??????? _DiffuseColor("Color",Color)=(1,1,1,1)

??? }

??? SubShader

??? {

??????? Pass

??????? {

??????????? Tags{ "LightMode"="ForwardBase" }

??????????? CGPROGRAM

??????????? //聲明頂點(diǎn)著色器

??????????? #pragma vertex vert

??????????? //聲明片元著色器

??????????? #pragma fragment frag

??????????? //引入U(xiǎn)nity內(nèi)置光照函數(shù)庫

??????????? #include "Lighting.cginc"

??????????? //定義外部屬性-漫反射顏色

??????????? float4 _DiffuseColor;

???????? ???//定義頂點(diǎn)著色器輸入結(jié)構(gòu)體

??????????? struct appdata

??????????? {

??????????????? //頂點(diǎn)坐標(biāo)

??????????????? float4 vertex : POSITION;

??????????????? //頂點(diǎn)法線

??????????????? float3 normal : NORMAL;

??????????? };

??????????? //定義頂點(diǎn)著色器輸出結(jié)構(gòu)體

??????????? struct v2f

??? ????????{

??????????????? //像素坐標(biāo)

??????????????? float4 vertex : SV_POSITION;

??????????????? //臨時(shí)變量:顏色

??????????????? fixed3 color : COLOR;

??????????? };

??????????? //頂點(diǎn)函數(shù)實(shí)現(xiàn)

??????????? v2f vert (appdata v)

??????????? {

??????????????? //定義頂點(diǎn)輸出結(jié)構(gòu)體對(duì)象

??????????????? v2f o;

??????????????? //頂點(diǎn)坐標(biāo)轉(zhuǎn)換到屏幕像素坐標(biāo)

??????????????? o.vertex = UnityObjectToClipPos(v.vertex);

??????????????? //獲取環(huán)境光

??????????????? float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

??????????????? //將頂點(diǎn)法線轉(zhuǎn)換到世界空間下,并做歸一化處理

??????????????? float3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));

??????????????? //將光照方向轉(zhuǎn)換到世界空間下,并做歸一化處理

??????????????? float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);

??????????????? //使用公式運(yùn)算

??????????????? fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(worldNormal,worldLight));

??????????????? //結(jié)合漫反射和環(huán)境光

??????????????? o.color = ambient + diffuse;

??????????????? //返回結(jié)果

??????????????? return o;

??????????? }

??????????? fixed4 frag (v2f i) : SV_Target

????? ??????{

??????????????? //輸入頂點(diǎn)顏色

??????????????? return fixed4(i.color,1.0);

??????????? }

??????????? ENDCG

??????? }

??? }

}

?

然后是逐像素:


Shader "AlbertShader/PixelDiffuse"

{

??? Properties

??? {

??????? _DiffuseColor("Color",Color)=(1,1,1,1)

??? }

??? SubShader

??? {

??????? Pass

??????? {

??????????? Tags{ "LightMode"="ForwardBase" }

??????????? CGPROGRAM

??????????? #pragma vertex vert

??????????? #pragma fragment frag

???????????

??????????? #include "Lighting.cginc"

?

??????????? float4 _DiffuseColor;

?????????? ?struct appdata

??????????? {

??????????????? float4 vertex : POSITION;

??????????????? float3 normal : NORMAL;

??????????? };

?

??????????? struct v2f

??????????? {

??????????????? float4 pos : SV_POSITION;

??????????????? fixed3 worldNormal : TEXCOORD0;

??????????? };

?

??????????? v2f vert (appdata v)

??????????? {

??????????????? v2f o;

??????????????? //把世界空間下的法線傳給片元著色器

??????????????? o.pos = UnityObjectToClipPos(v.vertex);

??????????????? o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);

? ??????????????return o;

??????????? }

???????????

??????????? fixed4 frag (v2f i) : SV_Target

??????????? {

??????????????? float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

??????????????? fixed3 worldNormal = normalize(i.worldNormal);

??????????????? fixed3? worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

??????????????? fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(worldNormal,worldLightDir));

??????????????? fixed3 color = diffuse + ambient;

??????????????? return fixed4(color,1.0);

??????????? }

??????????? ENDCG

??????? }

??? }

}

?

最后我們來看一下加入漫反射Shader后的效果

從左至右分別是逐頂點(diǎn)光照,逐像素光照,普通光照

之后的文章,我們會(huì)給大家?guī)砀嗟腢nityShader在實(shí)際項(xiàng)目中的使用。



想系統(tǒng)學(xué)習(xí)游戲開發(fā)的童鞋,歡迎訪問?http://levelpp.com/? ? ? ? ? ? ? ???

游戲開發(fā)攪基QQ群:869551769? ? ? ? ? ? ? ???

微信公眾號(hào):皮皮關(guān)

UnityShader系列之2:入門篇的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
蕲春县| 龙门县| 湘潭市| 东兰县| 平潭县| 鄂尔多斯市| 塘沽区| 富裕县| 平武县| 上蔡县| 义马市| 成安县| 太和县| 汪清县| 华阴市| 德兴市| 桃园市| 波密县| 龙海市| 莒南县| 南投县| 连山| 樟树市| 兰州市| 六安市| 晋江市| 广德县| 德清县| 新疆| 探索| 西平县| 天长市| 盈江县| 灵石县| 星子县| 长岭县| 南康市| 黑山县| 吉安市| 星子县| 固安县|