UnityShader學習記錄(三)

2021-08-28 09:55:09 字數 4213 閱讀 6910

這篇文章主要說一下shader裡面的透明效果,透明效果在unityshader中有兩種方式,透明度測試和透明度混合,透明度測試是比較霸道的透明演算法,它只有透明和不透明兩種情況,也就是說這個unityshader能實現的不是透明就是不透明,不會存在半透明現象,所以它的值就只有0和1兩種。那麼要想實現半透明效果的話就需要用到透明度混合了,透明度混合的值不像透明度測試一樣只用0和1,它是可以存在中間值的,所以實現半透明效果用透明度混合,而不需要實現半透明的情況下直接用透明度測試就ok。

透明度測試的shader有幾個新的知識點出現,因為要控制這個shader是否透明,所以需要乙個閾值來控制,上面也說到了,透明度測試的值只有0和1,所以閾值的範圍就是0,1,即:_cutoff("alphacutoff",range(0,1)) = 0.5

另外,做透明效果需要在subshader中標明渲染佇列和渲染順序以及渲染方式,之前的沒有標記是因為非透明效果的是會自動的進行深度測試以及渲染順序,而非透明效果要是不進行標記的話,會出現各種各樣意想不到的問題,因為unityshader內部會進行自動的渲染設定,為了避免這些問題,需要我們手動進行設定,即:#br

ignorprojector 設定shader不受投影器影響 為true。

rendertypr 設定shader歸組為transparentcutout透明度測試。

這些設定和設定在之後會有乙個文章單獨的記錄。

這裡我是寫在了subshader中表示只有這個subshader是進行這個操作的,如果寫在pass中就表示只有那個pass是進行這個操作,如果寫在全域性就表示整個shader都會進行這個操作。

設定好之後需要進行計算了,透明度計算公式:

clip(fixed4)

if(any(x<0))

discard;

換算到unity之後為:

clip(alphacolor.a - _cutoff)

if( ( alphacolor.a - _cutoff )<0 )

discard;

discard是放棄的意思相當於如果這個紋理的a值也就是透明度值減去閾值以後是小於0的,那麼我們就放棄這次的操作。

完整**如下:

shader "unlit/alphashader"

_color("color tint",color) = (1,1,1,1)

//控制透明度的閾值

_cutoff("alpha cutoff",range(0,1)) = 0.5

} subshader

pass

cgprogram

#pragma vertex vert

#pragma fragment frag

#include "lighting.cginc"

struct a2v

;struct v2f

;sampler2d _maintex;

float4 _maintex_st;

fixed4 _color;

fixed _cutoff;

v2f vert (a2v v)

fixed4 frag (v2f i) : sv_target

fixed3 albedo = alphacolor.rgb * _color.rgb;

fixed3 ambient = unity_lightmodel_ambient.xyz * albedo;

fixed3 diffuse = _lightcolor0.rgb * albedo * saturate(dot(worldnormal, worldlightdir));

fixed3 color = ambient + diffuse;

return fixed4(color,1.0);

}endcg

} }}

從上面的指令碼可以看出,除了增加了上面說的那些知識點以外,都是之前一樣的東西。

透明度混合開始說了它能實現半透明效果,透明度混合分兩種,關閉深度寫入和開啟深度寫入,深度寫入這個概念簡單一點來理解就是unityshader會自動判斷物體的距離以及遮擋,被遮擋的就不渲染,距離遠的渲染也是有影響的,但是半透明效果的話,透明物體後面的物體要顯示出來,所以我們要手動控制這個深度寫入。

首先閾值與透明度測試一樣,範圍也是0到1。

渲染設定,渲染佇列更改為transparent,其餘與透明度測試一致。

最重要的一點在pass中要關閉深度寫入,即:zwrite off 

設定源顏色的混合因子和目標顏色的混合因子,因為半透明是存在顏色混合的,所以:blendsrcalpha oneminussrcalpha

最後只需要在返回整體顏色值的時候將透明度的顏色的a值乘以閾值返回即可

完整**如下:(關閉深度測試)

shader "unlit/alphablendingshader"

_color("color tint",color) = (1,1,1,1)

_alphascale("alpha scale",range(0,1)) = 0.5

} subshader

//cull off

pass

zwrite off

blend srcalpha oneminussrcalpha

cgprogram

#pragma vertex vert

#pragma fragment frag

#include "lighting.cginc"

struct a2v

;struct v2f

;sampler2d _maintex;

float4 _maintex_st;

fixed _alphascale;

fixed3 _color;

v2f vert (a2v v)

fixed4 frag (v2f i) : sv_target

endcg

} }}

上面的**中有個call off 禁用了,開啟以後會發現物體內部的顯示也會出現,如果不寫的話物體內部就會被剔除。透明度測試也是一樣的。

關閉深度寫入實現的半透明會出現重疊或者重影的現象,為了防止同為透明物體出現遮擋或渲染順序出現問題,用開啟深度寫入的透明度混合實現,也就是用兩個pass來處理渲染模型,乙個用來開啟深度寫入乙個用來做正常的透明度混合,在開啟深度寫入的pass中寫:

zwrite on   

colormask0

colormask 0 意味著不寫入任何顏色通道,不會輸出任何顏色

完整**如下:

shader "unlit/alphablendingshader_self"

_color("color tint",color) = (1,1,1,1)

_alphascale("alpha scale",range(0,1)) = 0.5

} subshader

pass

cull front

zwrite on

colormask 0

} pass

zwrite off

blend srcalpha oneminussrcalpha

cgprogram

#pragma vertex vert

#pragma fragment frag

#include "lighting.cginc"

struct a2v

;struct v2f

;sampler2d _maintex;

float4 _maintex_st;

fixed4 _color;

fixed _alphascale;

v2f vert (a2v v)

fixed4 frag (v2f i) : sv_target

endcg

} }}

這裡出現兩個東西乙個cull front   乙個cull back

這個是實現雙面渲染的透明效果,沒有這個操作的話透明效果只是正面透明且背面透明是看不到的,這是因為在渲染過程中內部和背面被剔除了渲染圖元,為了實現背面和內部的透明渲染,用cull指令來控制要剔除哪個面的渲染圖元

cull back  背面不渲染

cull front  正面不渲染

cull off  關閉剔除功能

UnityShader學習記錄(一)

ps 本文章摘取自 unityshader入門精要 一書。之前一直想shader是乙個很難的東西,在接觸 unityshader入門精要 之後感覺也不是想象中的複雜,但是想要學好shader是乙個漫長的過程,基礎篇和初級篇看完之後感覺收穫挺大,為此,記錄一下。在進入shader之前,需要把渲染流水線...

unity shader 學習筆記

upgrade note replaced world2object with unity worldtoobject upgrade note replaced mul unity matrix mvp,with unityobjecttoclippos shader unity shader b...

Unity Shader 基礎知識記錄

首先謝謝大家的支援,其次如果你碰到什麼其他問題的話,歡迎來 我自己的乙個 討論群559666429來,大家一起找答案,共同進步 你能看到這篇文章,說明你最近在和我做一樣的事情 學習shader 由於也是剛開始學習,此處也是整理一些基礎的知識。unity官網資源 著色器 貓都能學會的unity sha...