小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

UnityShader快速上手指南(三)

 kiki的號 2017-04-17

簡介


這一篇還是一些基本的shader操作:裁剪、透明和法向量的應(yīng)用
(糾結(jié)了很久寫不寫這些,因?yàn)榇a很簡單,主要是些概念上的東西)

先來看下大概的效果圖:(從左到右依次是裁剪,透明,加了法向量的透明)

(好奇怪,為啥我字那么多,提示我少于150字)

這里寫圖片描述


裁剪


代碼


Shader "LT/Lesson3_Cull"
{
    Properties
    {
         _Color ("Color", Color) = (1, 1, 1, 1) 
    }
    SubShader
    {
        Pass
        {
            Cull Off 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            uniform float4 _Color;

            appdata_base vert ( appdata_base input)
            {
                input.texcoord = input.vertex ;
                input.vertex  = mul(UNITY_MATRIX_MVP, input.vertex );
                return input;
            }

            fixed4 frag (appdata_base input) : COLOR
            {
                if(input.texcoord.y < 0) {
                    discard;
                }
                return _Color; 
            }
            ENDCG
        }
    }
}

代碼的基本格式我就不介紹了,不熟的請看教程一

這里引入了一個(gè)新的東西: Cull Off


裁剪簡單的可以分為三種裁剪:擦除裁剪(discard),正面裁剪(Front)和背面裁剪(Back)

這里的Cull Off代表關(guān)閉unity自帶的背面裁剪(因?yàn)槿绻粚懙脑捘J(rèn)為Cull Back)


Cull Off 關(guān)閉裁剪
Cull Back 背面裁剪(默認(rèn))
Cull Front 正面裁剪

然后關(guān)于這個(gè)面的正反的界定,是通過法線來完成的,法線向量>0則為正

Cull Back 和 Cull Front Unity替我們完成了,如果需要簡單的裁掉正面和反面的話直接使用預(yù)制的就行了

(Q:如果我想同時(shí)裁正面和反面怎么處理? A:如果你要同時(shí)裁掉正面和反面,你的模型就不用顯示了好嘛)

這里我想通過模型的坐標(biāo)位置來裁面,所以關(guān)閉了Unity的自動裁剪

然后就是把頂點(diǎn)信息緩存下來:


input.texcoord = input.vertex ;

為了方便(同時(shí)也能提高性能,由于GPU是頻繁調(diào)用這些函數(shù),所以不管什么空間啊,計(jì)算啊都能省就?。?,我直接將數(shù)據(jù)存在了input對象中,然后又將input返回給frag使用(這里隨便選一個(gè)不用的字段用來緩存我們的位置信息就行了,注意vertex是要使用的,所以vertex不能用來緩存這個(gè)信息)

然后在frag中判斷我們緩存的坐標(biāo)信息,滿足條件就discard掉


                if(input.texcoord.y < 0) {
                    discard;
                }

這里的discard相當(dāng)于強(qiáng)行中斷該次渲染,也可以說成取消渲染,這樣就完成了我們的裁剪功能了

順帶一提,discard很消耗性能的,所以能不用還是就不用了(何況這里還多了一步if判斷語句),需要指定裁剪還是改模型來的高效,當(dāng)然如果需要?jiǎng)討B(tài)裁剪就需要這樣的代碼了


透明


還是先來代碼

代碼


Shader "LT/Lesson3_Transparent"
{
    Properties
    {
         _Color ("Color", Color) = (1, 1, 1, 0.5) 
    }
    SubShader
    {
        Tags { "Queue" = "Transparent" } 
        Pass
        {
            ZWrite Off 
            Blend One One 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            uniform float4 _Color;

            appdata_base vert ( appdata_base input)
            {
                input.vertex  = mul(UNITY_MATRIX_MVP, input.vertex );
                return input;
            }

            fixed4 frag (appdata_base input) : COLOR
            {
                return _Color; 
            }
            ENDCG
        }
    }
}

恩...這里呢代碼的內(nèi)容比較少,就是直接把外面設(shè)置的顏色應(yīng)用到物體上就完了

但是多了


Tags { "Queue" = "Transparent" } 
ZWrite Off 
Blend One One 

這三個(gè)東西

Tags { "Queue" = "Transparent" }

先來第一個(gè)Tags { "Queue" = "Transparent" }

大家可能看到有個(gè)Transparent會想要寫透明是不是必須要這句話,其實(shí)不然,這行代碼只是指定一個(gè)渲染順序而已,一般情況下是具體情況具體分析,比如你希望這個(gè)shader是渲染背景物體的時(shí)候,你可以設(shè)置為

"Queue" = "Background",需要時(shí)物體的時(shí)候設(shè)置為“Geometry”,其實(shí)對應(yīng)下來的就是一個(gè)數(shù)值,這個(gè)數(shù)值越小,越先渲染,然后從我們的渲染順序可以理解,先渲染的自然在背后了

下面列舉下常用的值對應(yīng)的名字


    "Background"。值為1000。比如用于天空盒。
    "Geometry"。值為2000。大部分物體在這個(gè)隊(duì)列。不透明的物體也在這里。這個(gè)隊(duì)列內(nèi)部的物體的渲染順序會有進(jìn)一步的優(yōu)化(應(yīng)該是從近到遠(yuǎn),early-z test可以剔除不需經(jīng)過FS處理的片元)。其他隊(duì)列的物體都是按空間位置的從遠(yuǎn)到近進(jìn)行渲染。
    "AlphaTest"。值為2450。已進(jìn)行AlphaTest的物體在這個(gè)隊(duì)列。
    "Transparent"。值為3000。透明物體。
    "Overlay"。值為4000。比如鏡頭光暈。

還有就是,用戶可以定義任意值,比如"Queue"="Geometry+10"


ZWrite Off

再來ZWriter Off,這句命令表示不寫入深度緩存

呃~~~,然后我們繼續(xù)來科普概念吧(由于語文不好,后面一大段話是從別的網(wǎng)站復(fù)制的)


1)什么是深度?
深度其實(shí)就是該像素點(diǎn)在3d世界中距離攝象機(jī)的距離,深度值(Z值)越大,則離攝像機(jī)越遠(yuǎn)。

(2)什么是深度緩存?
深度緩存中存儲著每個(gè)像素點(diǎn)(繪制在屏幕上的)的深度值!如果啟用了深度緩沖區(qū),在繪制每個(gè)像素之前,OpenGL會把它的深度值和已經(jīng)存儲在這個(gè)像素的深度值進(jìn)行比較。新像素深度值<原先像素深度值,則新像素值會取代原先的;反之,新像素值被遮擋,其顏色值和深度將被丟棄,最終屏幕顯示的就是深度緩存中深度對應(yīng)的像素點(diǎn)的顏色!(深度主要起的是比較的作用)

(3)什么是深度測試?
在深度測試中,默認(rèn)情況是將要繪制的新像素的z值與深度緩沖區(qū)中對應(yīng)位置的z值進(jìn)行比較,如果比深度緩存中的值小,那么用新像素的顏色值更新深度緩存中對應(yīng)像素的顏色值。

(4)為什么需要深度?
在不使用深度測試的時(shí)候,如果我們先繪制一個(gè)距離較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因?yàn)楹罄L制,會把距離近的物體覆蓋掉,這樣的效果并不是我們所希望的。而有了深度緩沖以后,繪制物體的順序就不那么重要了,都能按照遠(yuǎn)近(Z值)正常顯示,這很關(guān)鍵。(越后繪制的東西,距離相機(jī)就越近)

那么,在unity中,如果知道了渲染隊(duì)列,ZWrite,ZTest,如何確定哪個(gè)物體先顯示呢?
首先,unity先將渲染隊(duì)列中較前的進(jìn)行渲染,然后再執(zhí)行ZWrite,ZTest
ZWrite可以取的值為:On/Off,默認(rèn)值為On,代表是否要將像素的深度寫入深度緩存中
ZTest可以取的值為:Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off,默認(rèn)值為LEqual,代表如何將像素的顏色寫入深度緩存中,例如當(dāng)取默認(rèn)值的情況下,如果將要繪制的新像素的z值小于等于深度緩存中的值,則將用新像素的顏色值更新深度緩存中對應(yīng)像素的顏色值。需要注意的是,當(dāng)ZTest取值為Off時(shí),表示的是關(guān)閉深度測試,等價(jià)于取值為Always,而不是Never!Always指的是直接將當(dāng)前像素顏色(不是深度)寫進(jìn)顏色緩沖區(qū)中;而Never指的是不要將當(dāng)前像素顏色寫進(jìn)顏色緩沖區(qū)中,相當(dāng)于消失。

因?yàn)閆Write默認(rèn)值為On,ZTest默認(rèn)值為LEqual,所以這很好地解釋了為什么在unity中,距離相機(jī)近的東西會阻擋住距離相機(jī)遠(yuǎn)的東西。如果我們先繪制一個(gè)距離較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因?yàn)楹罄L制,會把距離近的物體覆蓋掉,這時(shí)我們可以通過修改ZWrite和ZTest來改變物體的遮擋關(guān)系!

恩,好,介紹完了深度這個(gè)玩意兒咯, 那來解釋下我們?yōu)樯兑P(guān)掉了(其實(shí)不關(guān)掉也可以,但是關(guān)掉GPU可以少做一步操作啊,提高性能性能性能性能性能性能,所以能關(guān)就關(guān)吧),因?yàn)槲覀円獙懙氖峭该靼。还芟群箜樞虻?,透明都可以看得?- -


Blend One One

最后是Blend One One,這是個(gè)大概念,這個(gè)命令是寫透明shader所必須的,因?yàn)樗x了透明的模式

然而,這玩意兒很簡單的,命令是


Blend SrcFactor DstFactor

然后這個(gè)Factor 支持:


One
值為1,使用此設(shè)置來讓源或是目標(biāo)顏色完全的通過。
Zero
值為0,使用此設(shè)置來刪除源或目標(biāo)值。
SrcColor
此階段的值是乘以源顏色的值。
SrcAlpha
此階段的值是乘以源alpha的值。
DstColor
此階段的值是乘以幀緩沖區(qū)源顏色的值。
DstAlpha
此階段的值是乘以幀緩沖區(qū)源alpha的值。
OneMinusSrcColor
此階段的值是乘以(1 - source color)
OneMinusSrcAlpha
此階段的值是乘以(1 - source alpha)
OneMinusDstColor
此階段的值是乘以(1 - destination color)
OneMinusDstAlpha
此階段的值是乘以(1 - destination alpha)

然后下面是常用的搭配:


Blend SrcAlpha OneMinusSrcAlpha // Alpha blending alpha混合
Blend One One // Additive 相加混合
Blend One OneMinusDstColor // Soft Additive 柔和相加混合
Blend DstColor Zero // Multiplicative 相乘混合
Blend DstColor SrcColor // 2x Multiplicative 2倍相乘混合

具體效果,大家可以自己改代碼看結(jié)果,這里就不多說了


帶法向量計(jì)算的透明


代碼


Shader "LT/Lesson3_Silhouette"
{
    Properties
    {
         _Color ("Color", Color) = (1, 1, 1, 0.5) 
    }
    SubShader
    {
        Pass
        {
            ZWrite Off 
            Blend SrcAlpha OneMinusSrcAlpha 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            uniform float4 _Color;

            appdata_base vert ( appdata_base input)
            {
                fixed3 tempNormal = normalize(mul(fixed4(input.normal, 0.0), _World2Object).xyz);
                fixed3 tempViewDir = normalize(_WorldSpaceCameraPos - mul(_Object2World, input.vertex).xyz);
                input.vertex  = mul(UNITY_MATRIX_MVP, input.vertex );
                input.normal.x = min(1.0, _Color.a / abs(dot(tempNormal, tempViewDir)));
                return input;
            }

            fixed4 frag (appdata_base input) : COLOR
            {
                return float4(float3(_Color.x,_Color.y,_Color.z), input.normal.x); 
            }
            ENDCG
        }
    }
}

這里沒啥新東西,但是代碼上把法向量用起來了(原理主要是通過法向量和攝像機(jī)朝向算出一個(gè)新的透明度用來替換而已)

解釋一下吧:


    fixed3 tempNormal = normalize(mul(fixed4(input.normal, 0.0), _World2Object).xyz);
    // 計(jì)算unity坐標(biāo)系下的法向量
    fixed3 tempViewDir = normalize(_WorldSpaceCameraPos - mul(_Object2World, input.vertex).xyz);
    // 計(jì)算unity坐標(biāo)系啊的攝像機(jī)的向量
    input.normal.x = min(1.0, _Color.a / abs(dot(tempNormal, tempViewDir)));
    // 將兩個(gè)向量點(diǎn)乘然后換算給設(shè)定顏色的alpha通道,并緩存起來
    // 至于為啥要點(diǎn)乘,然后用Color.a來除,這個(gè)是算法問題啦:
    // a = min(1, a/ |V·N|),公式是書上來的,數(shù)學(xué)問題了,不做贅述
    
    return float4(float3(_Color.x,_Color.y,_Color.z), input.normal.x); 
    // 使用設(shè)置的顏色的rgb值和算出來的新的alpha值

由于個(gè)人很喜歡這個(gè)效果,所以再來次效果展示

這里寫圖片描述

這樣是不是有一點(diǎn)簡單的立體效果咯捏(這不是光照,真的光照的反射啥的下一篇教程講)


總結(jié)


本篇教程的東西都很基礎(chǔ),但是在以后寫shader的過程中會用的很平凡,所以還是單獨(dú)拿出來講了一下,與我們的快速上手指南其實(shí)有點(diǎn)背道而馳 o(╯□╰)o ,但是為了后面不會看不懂,大家還是多自己寫寫熟悉一下,比如使用discard和Cull配合兩個(gè)Pass寫一個(gè)正反面渲染不同顏色的shader,利用前面講的SinTime和法向量啥的寫一個(gè)動態(tài)變化效果

還是那句話,又不懂得,QQ:821580467


    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多