做房產(chǎn)應(yīng)看的網(wǎng)站下載微信
本系列為作者學(xué)習(xí)UnityShader入門精要而作的筆記,內(nèi)容將包括:
- 書本中句子照抄 + 個(gè)人批注
- 項(xiàng)目源碼
- 一堆新手會(huì)犯的錯(cuò)誤
- 潛在的太監(jiān)斷更,有始無終
我的GitHub倉(cāng)庫(kù)
總之適用于同樣開始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。
文章目錄
- 使用噪聲
- 上節(jié)補(bǔ)充:smoothstep
- 消融效果
- 水波效果
- 全局霧效
使用噪聲
在有些時(shí)候,向規(guī)則的事物里面添加一些雜亂無章的效果,往往會(huì)有奇效。而這些雜亂無章的效果的來源就是噪聲。在本章中我們將學(xué)習(xí)如何使用噪聲來模擬一些特效。
上節(jié)補(bǔ)充:smoothstep
這篇文章很好的描述了smoothstep實(shí)現(xiàn)了什么樣的效果。實(shí)際實(shí)現(xiàn)了對(duì)一個(gè)圓形范圍的邊緣模糊Shader實(shí)驗(yàn)室: smoothstep函數(shù)
消融效果
消融效果往往使用在角色死亡,地圖燒毀等現(xiàn)象上。消融的效果往往是從不同區(qū)域開始,然后往看似隨機(jī)的方向擴(kuò)散,最后整個(gè)物體消失不見。
Shader
Shader "Custom/Dissolve_Copy"
{Properties{_BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0// _LineWidth代表了周邊延申的效果線_LineWidth("Burn Line Width", Range(0.0, 10)) = 0.1_MainTex ("Base (RGB)", 2D) = "white" {}_BumpMap ("Normal Map", 2D) = "bump" {}_BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)_BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)_BurnMap("Burn Map", 2D) = "white"{}}SubShader{Tags { "RenderType"="Opaque" "Queue"="Geometry"}Pass {Tags { "LightMode"="ForwardBase" }// 不要剔除背面,不然裁剪面片時(shí)會(huì)發(fā)現(xiàn)沒有背面Cull OffCGPROGRAM#include "Lighting.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbase#pragma vertex vert#pragma fragment fragfixed _BurnAmount;fixed _LineWidth;sampler2D _MainTex;sampler2D _BumpMap;fixed4 _BurnFirstColor;fixed4 _BurnSecondColor;sampler2D _BurnMap;float4 _MainTex_ST;float4 _BumpMap_ST;float4 _BurnMap_ST;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float2 uvMainTex : TEXCOORD0;float2 uvBumpMap : TEXCOORD1;float2 uvBurnMap : TEXCOORD2;float3 lightDir : TEXCOORD3;float3 worldPos : TEXCOORD4;SHADOW_COORDS(5)};v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);TANGENT_SPACE_ROTATION;o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;TRANSFER_SHADOW(o);return o;}fixed4 frag(v2f i) : SV_Target {// 對(duì)噪聲紋理進(jìn)行采樣fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;// 根據(jù)_BurnAmount來clip像素,保留白色去除黑色clip(burn.r - _BurnAmount);float3 tangentLightDir = normalize(i.lightDir);fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));// 對(duì)裁剪掉的部分進(jìn)行混合顏色渲染fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);// 這一部分渲染的顏色是根據(jù)smoothstep獲取的形狀渲染的,// 被裁剪部分=0,因此經(jīng)過smoothstep后周邊模糊區(qū)域會(huì)保留,中心區(qū)域裁剪,渲染范圍是裁剪部分區(qū)域 + _LineWidth// 而越靠近裁剪部分的像素渲染越接近firstColorfixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);// 深化顏色,看起來亮一點(diǎn)burnColor = pow(burnColor, 5);UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);// 最終再混合光照和燃燒特效色fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001, _BurnAmount));return fixed4(finalColor, 1);}ENDCG}// Pass to render object as a shadow casterPass {Tags { "LightMode" = "ShadowCaster" }CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_shadowcaster#include "UnityCG.cginc"fixed _BurnAmount;sampler2D _BurnMap;float4 _BurnMap_ST;struct v2f {V2F_SHADOW_CASTER;float2 uvBurnMap : TEXCOORD1;};v2f vert(appdata_base v) {v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;// 對(duì)陰影也需要剔除clip(burn.r - _BurnAmount);SHADOW_CASTER_FRAGMENT(i)}ENDCG}}FallBack "Diffuse"
}
例如火焰焚毀效果
發(fā)現(xiàn)配合不同的噪聲貼圖可以實(shí)現(xiàn)很多有意思的效果,例如掃描線重建
或者這樣的沙化效果,總而言之只要是類似的隨時(shí)間漸變效果應(yīng)當(dāng)都是能夠使用噪聲貼圖實(shí)現(xiàn)的,只是需要充分發(fā)揮想象力
水波效果
在模擬實(shí)時(shí)水面的時(shí)候,我們往往也會(huì)使用噪聲紋理作為高度圖,不斷修改水面的法線方向,以模擬水不斷流動(dòng)的效果。我們會(huì)使用和時(shí)間相關(guān)的變量來對(duì)噪聲紋理進(jìn)行采樣,當(dāng)?shù)玫椒ň€信息后再進(jìn)行正常的反射 + 折射運(yùn)算,得到最終的水面波動(dòng)效果
在之前我們寫過一個(gè)實(shí)現(xiàn)了菲涅爾反射的玻璃效果,現(xiàn)在我們想要實(shí)現(xiàn)水波,自然也要使用菲涅爾反射,此外為了實(shí)現(xiàn)水面的波動(dòng)效果,我們可以用一張?jiān)肼曎N圖,并不斷進(jìn)行偏移采樣來模擬水面的隨機(jī)波動(dòng)。以實(shí)現(xiàn)波光粼粼的效果。
Shader "Custom/WaterWave_Copy"
{Properties{_Color ("Main Color", Color) = (1,1,1,1)_MainTex ("Base Tex", 2D) = "white" {}_WaveMap ("Wave Map",2D) = "bump"{}_Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}_WaveXSpeed ("Wave Horizontal Speed", Range(-0.1, 0.1)) = 0.01_WaveYSpeed ("Wave Vertical Speed", Range(-0.1, 0.1)) = 0.01_Distortion ("Distortion", Range(0, 100)) = 10}SubShader{Tags { "Queue"="Transparent" "RenderType"="Opaque" }// 抓取不透明物體渲染后的緩存,并保存到_RefractionTex紋理中// 此處GrabPass在渲染水面紋理之前,因此抓取的是未渲染水面時(shí)的場(chǎng)景畫面GrabPass { "_RefractionTex" }Pass{Tags{ "LightMode"="ForwardBase" }CGPROGRAM#include "UnityCG.cginc"#include "Lighting.cginc"#pragma multi_compile_fwdbase#pragma vertex vert#pragma fragment fragfixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _WaveMap;float4 _WaveMap_ST;samplerCUBE _Cubemap;fixed _WaveXSpeed;fixed _WaveYSpeed;float _Distortion; sampler2D _RefractionTex;float4 _RefractionTex_TexelSize;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT; float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float4 scrPos : TEXCOORD0;float4 uv : TEXCOORD1;float4 TtoW0 : TEXCOORD2; float4 TtoW1 : TEXCOORD3; float4 TtoW2 : TEXCOORD4; };v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.scrPos = ComputeGrabScreenPos(o.pos);o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);o.uv.zw = TRANSFORM_TEX(v.texcoord, _WaveMap);// 用于計(jì)算光照模型(菲涅爾反射)。需要用到世界空間下的切線方向float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 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);fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));// 計(jì)算水波紋理在uv上的采樣速度float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);// 對(duì)法線紋理采樣并將法線紋理轉(zhuǎn)換回切線空間// 此處為了模擬水波的不規(guī)則運(yùn)動(dòng),bump1邊對(duì)speed正方向采樣,bump2對(duì)負(fù)方向采樣,并將兩種法線紋理采樣都應(yīng)用上去fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;fixed3 bump = normalize(bump1 + bump2);// 將場(chǎng)景的像素與法線進(jìn)行混合以實(shí)現(xiàn)水面波動(dòng)和場(chǎng)景畫面的顏色值的混合// _Distortion越大,水體背后的物體看起來變形程度越大float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;// 對(duì)z坐標(biāo)進(jìn)行相乘,以模擬深度越大,折射程度越大的效果i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;// 將采樣法線貼圖計(jì)算的切線空間坐標(biāo)變換到世界空間下bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));// 采樣主紋理并計(jì)算菲涅爾反射fixed4 texColor = tex2D(_MainTex, i.uv.xy + speed);fixed3 reflDir = reflect(-viewDir, bump);fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb * _Color.rgb;fixed fresnel = pow(1 - saturate(dot(viewDir, bump)), 4);fixed3 finalColor = lerp(refrCol,reflCol,fresnel);//fixed3 finalColor = reflCol * fresnel + refrCol * (1 - fresnel);return fixed4(finalColor, 1);}ENDCG}}// 不投射陰影FallBack Off
}
全局霧效
從代碼上看來其實(shí)就是對(duì)原來的霧效后處理進(jìn)行了一個(gè)噪聲紋理貼圖的采樣。
此處就不展開了