国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

這篇具有很好參考價值的文章主要介紹了【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

《入門精要》中模擬玻璃是用了Unity里的一個特殊的Pass來實(shí)現(xiàn)的,這個Pass就是GrabPass,比起上一篇博客實(shí)現(xiàn)鏡子的方法,這個方法我認(rèn)為相對復(fù)雜,因此在實(shí)現(xiàn)之前需要對GrabPass及實(shí)現(xiàn)原理做一個更加詳細(xì)的介紹。


1 效果及代碼

1.1 效果

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

1.2 Shader完整代碼

Shader "Unity Shaders Book/Chapter 10/GlassRefraction"
{
    //Properties
    Properties {
        _MainTex ("Main Tex", 2D) = "white" {}  //玻璃材質(zhì)紋理
        _Cubemap ("EM", Cube) = "_Skybox" {}
        _BumpMap ("Bump Map", 2D) = "bump" {}  //玻璃法線紋理
        //control the distortion of refraction
        _Distortion ("Distortion", range(0, 100)) = 10
        _RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 1.0
    }
    
    SubShader {
        //Queue must be transparent, opaque objects will be drawn before
        Tags { "Queue"="Transparent" "RenderType"="Opaque" }

        //define a pass to grab the screen behind the object,
        //see the result by using "_RefractionTex"
        GrabPass {"_RefractionTex"}

        Pass {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            //Properties
            sampler2D _MainTex;
            float4 _MainTex_ST;
            samplerCUBE _Cubemap;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _Distortion;
            fixed _RefractAmount;
            //remember to add:
            sampler2D _RefractionTex;
            //get the texel size:
            float4 _RefractionTex_TexelSize; 
            
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 tangent : TANGENT;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float4 uv : TEXCOORD0;
                float4 TtoW0 : TEXCOORD1;
                float4 TtoW1 : TEXCOORD2;
                float4 TtoW2 : TEXCOORD3;
                float4 srcPos : TEXCOORD4;
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                //抓取屏幕圖像的采樣坐標(biāo)
                o.srcPos = ComputeGrabScreenPos(o.pos);
                o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldNormal = UnityObjectToWorldNormal(v.normal).xyz;
                float3 worldTangent = UnityObjectToWorldNormal(v.tangent).xyz;
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                //計(jì)算切線空間 -> 世界空間的矩陣,只需要3x3
                //按列擺放
                o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

                return o;
            }

            fixed4 frag(v2f i) :SV_Target {
                float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
                //計(jì)算光照需要參數(shù):
                fixed3 worldlightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                fixed3 worldviewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                //對紋理采樣+解碼,得到法線方向
                fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
                
                //由于這里需要模擬的是玻璃的折射效果,因此不能是這種常規(guī)的法線紋理的偏移:
                //bump.xy *= _BumpScale;
                //bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));

                //開始實(shí)現(xiàn)折射效果
                float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
                i.srcPos.xy = offset + i.srcPos.xy;
                //采樣得到“折射”顏色:
                fixed3 refractColor = tex2D(_RefractionTex, i.srcPos.xy/i.srcPos.w).rgb;

                bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

                //開始環(huán)境映射:
                fixed3 reflectDir = reflect(-worldviewDir, bump);
                fixed4 texColor = tex2D(_MainTex, i.uv.xy);
                fixed3 reflectColor = texCUBE(_Cubemap, reflectDir).rgb * texColor.rgb;

                fixed3 finalColor = reflectColor * (1 - _RefractAmount) + refractColor * _RefractAmount;
                return fixed4(finalColor, 1.0);
            }
            ENDCG
        }
    }
    FallBack  "Diffuse"
}

2 一些重點(diǎn)過程

2.1 制作場景

場景物體拜訪和貼圖完全參考《入門精要》:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

以及當(dāng)前場景的Cubemap的創(chuàng)建:由于相同項(xiàng)目下之前已經(jīng)在Assets -> Edit加了一個可以獲取場景中某個GameObject角度的Cubemap,直接按照相似的方法創(chuàng)建了創(chuàng)建過程可以參考【Unity Shader】Unity中如何創(chuàng)建Cubemap?

2.2 關(guān)于渲染隊(duì)列設(shè)置

乍一看,SubShader的標(biāo)簽設(shè)置好像是前后矛盾的,?渲染隊(duì)列Queue是Transparent透明的,而當(dāng)前shader的渲染類型RenderType確是不透明:

Tags { "Queue"="Transparent" "RenderType"="Opaque" }
GrabPass {"_RefractionTex"}

設(shè)置Queue的作用

我們上效果,如果不加上"Queue"="Transparent",效果如下:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

?當(dāng)前的Shader是掛在外面的Cube上的,從上圖效果和1.1的效果對比可以看出,Queue設(shè)置為Transparent是為了保證當(dāng)前屏幕空間畫面里的比Cube深度大、但是是不透明的物體(默認(rèn)的Queue就是不透明)也能渲染并呈現(xiàn)出來,達(dá)到“透過玻璃觀察”的效果。

設(shè)置RenderType的作用

還跟上面一樣,假設(shè)把"RenderType"="Opaque"去掉,會發(fā)現(xiàn)效果跟1.1的沒有任何變化。這是因?yàn)椋enderType其實(shí)是提前給當(dāng)前的Shader歸類了,為了方便之后使用著色器替換(Shader Relacement)的時候,當(dāng)前Shader能被正確的使用。至于什么是著色器替換,后面會涉及到,這里就先不解釋了,挖個坑以后填。

2.3 2種GrabPass的使用方法

參考ShaderLab:GrabPass - Unity 手冊,從官方文檔中可知GrabPass是ShaderLab語法中的一員,是包含在SubShader內(nèi)的一種特殊的通道類型,它直接定義了一個額外的抓取屏幕圖像的Pass,把即將繪制對象時的屏幕內(nèi)容抓取到某個紋理中,這個紋理可以在后面的Pass中被使用去做一些效果。它的使用方式通常有兩種:

GrabPass {}

即直接在Pass語義塊前添加GrabPass {},{}里啥也不寫,那么后續(xù)抓取屏幕圖像的Pass會使用_GrabTexture來訪問屏幕圖像。這種方法看似方便,省去了定義一個新texture的麻煩。但當(dāng)場景中多個物體都需要這種形式來抓取屏幕時(我理解的是有多個物體需要做出類似“玻璃”的效果),Unity都會為每個物體單獨(dú)執(zhí)行一次這個Pass的抓取操作,每個物體都會生成屬于自己的_GrabTexture,這樣的效果雖好,但代價是很大的。

GrabPass {"TextureName"}

就像上述代碼中的:

GrabPass {"_RefractionTex"}

給我們Pass抓取屏幕圖像定義一個專屬的、名為"_RefractionTex"的紋理,后續(xù)的Pass中如果需要使用,就可以通過這個名稱來訪問抓取屏幕圖像的紋理啦!比如上述代碼中的:

fixed3 refractColor = tex2D(_RefractionTex, i.srcPos.xy/i.srcPos.w).rgb;

就是直接使用了定義的紋理名稱來訪問這個紋理。這樣使用方法的好處是,同一個屏幕下多個需要GrabPass的物體都使用同一次渲染出的紋理,也就是僅進(jìn)行一次GrabPass的抓取圖像操作,這樣就可以大大節(jié)省消耗!而且大部分情況下,都使用一張抓取的圖像已經(jīng)能滿足效果需求了。

二者的對比

?這里我們還是用到了Unity提供的Frame Debug,同時為了更好的對比效果,我在場景中多添加了一個想實(shí)現(xiàn)透明效果的Cube,這里僅看透明物體的渲染步驟。

使用GrabPass {"_RefractionTex"}時,可以發(fā)現(xiàn)步驟中兩個Cube是共用同一張Texture的,僅Grab了一次:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

而當(dāng)使用GrabPass {}時,Grab了兩次:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

兩次的RenderTexuter分別是:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

二者的消耗對比(左GrabPass {"_RefractionTex"};右GrabPass {}),可以發(fā)現(xiàn)右邊消耗明顯比左邊大:

【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果

2.4 獲取紋素大?。篲TexelSize

這里是為了提一提Shader中定義的:

//get the texel size:
float4 _RefractionTex_TexelSize;

以后的使用中如果想要獲取某張紋理的紋素大小,就可以在紋理名稱后加上_TexelSize啦!這個有點(diǎn)類似_MainTex_ST,都是Unity Shader的內(nèi)置屬性~

2.5 ComputerGrabScreenPos函數(shù)

這是一個Unity Shader的內(nèi)置函數(shù),ComputerGrabScreenPos()括號中輸入裁剪空間下的頂點(diǎn)位置坐標(biāo),可以得到當(dāng)前被抓取的屏幕圖像的屏幕坐標(biāo)。關(guān)于屏幕坐標(biāo)獲得好像有另一個函數(shù)?——ComputerScreenPos,那么問題來了:為什么不用ComputerScreenPos?關(guān)于這個問題,可以先保留著,我將在接下來的博客中仔細(xì)說明(又給自己挖了一個坑。。。)這里僅需要知道ComputerGrabScreenPos()的作用就行!

2.6?如何實(shí)現(xiàn)折射效果?

關(guān)于折射,我們好像真的學(xué)過并使用過一個折射相關(guān)的Unity內(nèi)置函數(shù)——Refract(i, n, ri),但這里實(shí)現(xiàn)折射并不是真的要實(shí)現(xiàn)折射光的效果(太消耗啦?。遣捎?strong>GrabPass+給屏幕坐標(biāo)一個偏移的方式實(shí)現(xiàn)玻璃的折射效果。

GrabPass在前面已經(jīng)介紹過了,這里過一遍如何給屏幕坐標(biāo)偏移,主要體現(xiàn)在如下代碼:

fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
//由于這里需要模擬的是玻璃的折射效果,因此不能是這種常規(guī)的法線紋理的偏移:
//bump.xy *= _BumpScale;
//bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));

//開始實(shí)現(xiàn)折射效果
float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
i.srcPos.xy = offset + i.srcPos.xy;
//采樣得到“折射”顏色:
fixed3 refractColor = tex2D(_RefractionTex, i.srcPos.xy/i.srcPos.w).rgb;

對bump偏移

如果不記得如何在世界空間使用法線紋理了,可以先去看看【Unity Shader】紋理實(shí)踐5.0:世界空間下使用法線紋理,如果僅實(shí)現(xiàn)法線紋理但并不考慮玻璃效果,直接給bump一個傳統(tǒng)的變化就行,但這里需要加上玻璃的折射效果,因此還需要結(jié)合定義的_Distortion變量和_RefractionTex_TexelSize變量對bump“做手腳”。

  • _Distorion——控制折射的扭曲程度,其實(shí)它的道理跟傳統(tǒng)應(yīng)用中的“_BumpScale”是一樣的
  • _RefractionTex_TexelSize——偏移量的大小,當(dāng)然是根據(jù)紋理坐標(biāo)而偏移

獲取折射顏色

tex2D(_RefractionTex, i.srcPos.xy/i.srcPos.w)這里用了一個透視除法!這里涉及到了如何在Unity中獲取片元在屏幕上的像素位置,這一點(diǎn)之前在學(xué)習(xí)基礎(chǔ)理論時忽略了,后期會再補(bǔ)上,這里就不贅述(好家伙,又挖了一個坑。。。)。

最終呈現(xiàn)的顏色

fixed3 finalColor = reflectColor * (1 - _RefractAmount) + refractColor * _RefractAmount;

這里用了一個_RefractAmount巧妙地控制了折射和反射的占比(跟之前的環(huán)境映射中實(shí)現(xiàn)折射效果一樣的操作),其實(shí)就是一個自行給定的菲涅爾項(xiàng)。


關(guān)于實(shí)現(xiàn)玻璃效果的過程梳理到這就結(jié)束啦!

后面會再出一個關(guān)于Unity中GrabPass的使用、包括GrabPass和AlphaBlend的區(qū)別、URP下的GrabPass實(shí)現(xiàn)方案等等,以及《入門精要》中提到的一個Command Buffers這個新概念,這些點(diǎn)真的有太多太多可以學(xué)習(xí)的內(nèi)容了。文章來源地址http://www.zghlxwxcb.cn/news/detail-488969.html

到了這里,關(guān)于【Unity Shader】Unity中利用GrabPass實(shí)現(xiàn)玻璃效果的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Unity中Shader抓取屏幕并實(shí)現(xiàn)扭曲效果(優(yōu)化)

    Unity中Shader抓取屏幕并實(shí)現(xiàn)扭曲效果(優(yōu)化)

    對上一篇中實(shí)現(xiàn)的shader進(jìn)行優(yōu)化 1、定義結(jié)構(gòu)體用于傳入頂點(diǎn)坐標(biāo)系 struct appdata { float4 vertex : POSITION; //從應(yīng)用程序階段的輸入,多加一個uv,用于對扭曲紋理的采樣 float2 uv : TEXCOORD; }; 2、因?yàn)閁nityObjectToClipPos是從本地空間轉(zhuǎn)換到裁剪空間,但是沒有進(jìn)行透視除法,所以需要對其

    2024年02月03日
    瀏覽(24)
  • Unity Shader學(xué)習(xí)記錄(11) ——透明效果的實(shí)現(xiàn)方式

    Unity Shader學(xué)習(xí)記錄(11) ——透明效果的實(shí)現(xiàn)方式

    1 透明效果的兩種方法 透明是游戲中經(jīng)常要使用的一種效果。在實(shí)時渲染中要實(shí)現(xiàn)透明效果,通常會在渲染模型時控制它的透明通道(Alpha Channel)。當(dāng)開啟透明混合后,當(dāng)一個物體被渲染到屏幕上時,每個片元除了顏色值和深度值之外,它還有另一個屬性一一透明度。 當(dāng)透明度

    2024年02月07日
    瀏覽(24)
  • unity shader 入門 全透明與半透明效果實(shí)現(xiàn)

    unity shader 入門 全透明與半透明效果實(shí)現(xiàn)

    片元函數(shù)的fixed4類型的返回值的第4位即為阿爾法值,0代表完全不顯示(透明),1代表完全顯示。中間的數(shù)值代表半透明。但只修改這個值是不能直接修改透明度的,因?yàn)檫€要對隊(duì)列等進(jìn)行修改。 本文介紹透明度測試與透明度混合,前者只能制作全透明效果,后者可制作半透明

    2024年02月14日
    瀏覽(24)
  • 【unity實(shí)戰(zhàn)】使用shader和shader Graph實(shí)現(xiàn)2d圖片描邊效果(附源碼)

    【unity實(shí)戰(zhàn)】使用shader和shader Graph實(shí)現(xiàn)2d圖片描邊效果(附源碼)

    最近在學(xué)習(xí)shader Graph相關(guān)內(nèi)容,其實(shí)關(guān)于實(shí)現(xiàn)2d圖片描邊效果,網(wǎng)上可以看到很多教程,但是我發(fā)現(xiàn)大多數(shù)都是基于比較老舊的2018unity版本,可是我們實(shí)際開發(fā)使用可能是比較新的2021及以上版本,差別還是有的,實(shí)際在升級或者使用過程中,會遇到諸多問題,而且也很少有人

    2024年02月16日
    瀏覽(98)
  • 【實(shí)現(xiàn)100個unity特效】shader實(shí)現(xiàn)3D物品閃光和描邊效果

    【實(shí)現(xiàn)100個unity特效】shader實(shí)現(xiàn)3D物品閃光和描邊效果

    線狀映射圖片 配置,按該shader新增材質(zhì) Outline Width控制描邊 Line Speed控制閃光速度 當(dāng)然,還可以修改對應(yīng)的顏色 效果演示 贈人玫瑰,手有余香!如果文章內(nèi)容對你有所幫助,請不要吝嗇你的 點(diǎn)贊評論和關(guān)注 ,以便我第一時間收到反饋,你的每一次 支持 都是我不斷創(chuàng)作的最

    2024年01月25日
    瀏覽(92)
  • 【實(shí)現(xiàn)100個unity特效之2】使用shader和shader Graph實(shí)現(xiàn)2d圖片描邊效果(附源碼)

    【實(shí)現(xiàn)100個unity特效之2】使用shader和shader Graph實(shí)現(xiàn)2d圖片描邊效果(附源碼)

    最近在學(xué)習(xí)shader Graph相關(guān)內(nèi)容,其實(shí)關(guān)于實(shí)現(xiàn)2d圖片描邊效果,網(wǎng)上可以看到很多教程,但是我發(fā)現(xiàn)大多數(shù)都是基于比較老舊的2018unity版本,可是我們實(shí)際開發(fā)使用可能是比較新的2021及以上版本,差別還是有的,實(shí)際在升級或者使用過程中,會遇到諸多問題,而且也很少有人

    2024年01月21日
    瀏覽(97)
  • 【unity插件】Shader實(shí)現(xiàn)UGUI的特效——UIEffect為 Unity UI 提供視覺效果組件

    【unity插件】Shader實(shí)現(xiàn)UGUI的特效——UIEffect為 Unity UI 提供視覺效果組件

    一般的shader無法直接使用在UI上,需要在shader中定義特定的面板參數(shù),今天就來推薦github上大佬做的一套開源的一系列UGUI,Shader實(shí)現(xiàn)的特效——UIEffect 為 Unity UI 提供視覺效果組件。 https://github.com/Ankh4396/UIEffect 讓我們用效果來裝飾你的UI!您可以根據(jù)需要從腳本和檢查器中控

    2024年02月04日
    瀏覽(61)
  • CSS實(shí)現(xiàn)磨砂玻璃(毛玻璃)效果樣式

    要實(shí)現(xiàn)磨砂玻璃背景,可以使用 CSS3 中的 ::before 偽元素和 backdrop-filter 屬性,結(jié)合 opacity 屬性和 blur() 函數(shù)來實(shí)現(xiàn)。 具體實(shí)現(xiàn)步驟如下: 創(chuàng)建一個具有背景的元素,例如一個 div 元素。 使用 ::before 偽元素為元素添加一個半透明的背景層。 在這個示例中,設(shè)置了 ::before 偽元素

    2024年02月05日
    瀏覽(94)
  • Unity Shader學(xué)習(xí)3:透明效果

    Unity Shader學(xué)習(xí)3:透明效果

    Unity中的透明效果由透明通道控制(RGBA中的A),其值為0是完全透明,為1時完全不透明。有兩種方法可以實(shí)現(xiàn)透明效果: 透明度測試(Alpha Test) 和 透明度混合(Alpha Blend) 。 透明度測試是指通過特定的條件(通常是Alpha通道的值是否超過某個閾值)來判斷片元是否透明,只

    2024年01月19日
    瀏覽(84)
  • unity 利用Scroll View實(shí)現(xiàn)滑動翻頁效果

    unity 利用Scroll View實(shí)現(xiàn)滑動翻頁效果

    1.在Hierarchy視圖右鍵創(chuàng)建UI-Scroll View。 Scrollbar可根據(jù)自己需求選擇是否刪除,我這里制作的翻頁日歷用不上我就刪除了。 connect節(jié)點(diǎn)掛上Grid Layout Group組件,參數(shù)屬性可參考unity API。 下面是具體實(shí)現(xiàn)代碼 ?onLeft和onRight綁定左右翻頁按鈕事件 ?

    2024年01月25日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包