日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

带顶点动画的护盾效果——UnityShader学习笔记

發(fā)布時(shí)間:2024/3/13 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 带顶点动画的护盾效果——UnityShader学习笔记 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 自言自語(yǔ)
  • 一、效果
  • 二、C#
  • 三、Shader
  • 總結(jié)


自言自語(yǔ)

最近又是很久沒(méi)有更新筆記了。原因有二。
一、最近一直再啃一個(gè)看起來(lái)酷炫的護(hù)盾效果 啃了好久啊。直至效果滿意 也理解了。 這個(gè)是一個(gè)同事傳授給我的 我算是偷師。
二、前不久難得出去旅游了一趟。五六年了,第一次出去旅游。真開(kāi)心。不想回來(lái)。
所以導(dǎo)致很久沒(méi)更新筆記。今日就接著更新吧

一、效果

GIF限制大小,就不穿了。 放一個(gè)靜態(tài)圖,方便以后能快速查找區(qū)分。

二、C#

與上一筆記代碼一樣。就不重復(fù)貼了

三、Shader

同樣源碼貼出。并對(duì)上個(gè)筆記中不理解的地方 重新理解后做了更詳細(xì)的注釋筆記。 誰(shuí)讓我腦子笨呢 不寫(xiě)詳細(xì)點(diǎn)以后就又看不懂了。

Shader "ShaderFX/ShaderPractiseFX_BeeSphere" {Properties{[Header(BeeShape IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)]_EdgeMask ("EdgeMask", 2D) = "White" {}[HDR]_EdgeColor("BeeColor",Color) = (1,1,1,1)_BeeNoiseMap("EdgeNoiseMap",2D)="white"{}[HDR]_BeeColor("BeeEmissive",Color)=(1,1,1,1)[Space(10)][Header(RimColor IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)][HDR]_rimColor("RimColor",Color)=(1,1,1,1)_rimSmooth("RimSmooth",Range(0.001,4))=0.5_rimStrenth("RimStrenth",Float)=1_ShieldEdgeSmooth("ShieldEdgeSmooth",Range(0,10)) = 0.5_ShieldEdgePow("ShieldEdgePow",Range(0,2)) =1[Space(10)][Header(Distortion IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)][HDR]_DistortionColor("DistortionColor",Color) = (1,1,1,1)_NoiseIntensityDistor("NoiseDistortion",Float) =1_DistortionFactor("DistortionFactor",Float) = 1_DistortionSmooth ("DistortionSmooth",Float) =1_PositionOffset("DistortionPos",Vector) = (0,0,0,0)[Space(10)][Header(HitWave IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)]_rampmap("FadeRampTex",2D) = "white"{}[HDR]_WaveColor("WaveColor",Color) =(1,1,1,1)_NoiseMap ("NoiseMap",2D)="white"{}_WaveNoiseIntensity("WaveNoiseIntensity",Float) = 1_FadeScale ("WaveFadeScale",Float) = 1_FadeSmoosth("FadeSmooth",Float) = 0.5_FadeIntensity("FadeIntensity",Float) = 1_OffsetDistance("OffsetDistance",Float) = 1_OffsetWidth("OffsetWidth",Float) = 1[HDR]_NewVertexColor("OffsetColor",Color) = (1,1,1,1)[Space(10)][Header(FlowMap IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)][HDR]_FlowColor("FlowColor",Color) = (1,1,1,1)_FlowLightMap("FlowLightMap",2D)="white"{}_FlowMap("FlowMap",2D)="white"{}_FlowSpeed ("FlowSpeed",Float) = 0.2_FlowIntensityDirectional("FlowIntensityDirectional",Vector)=(0,0,0,0)[Space(10)][Header(Specular IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)][HDR]_specularColor("SpecularColor",Color) = (1,1,1,1)_Gloss("_Gloss",Float) = 100}SubShader{//Transparent+1 是為了在透明物體后邊渲染 不然看不見(jiàn)透明物體Tags { "RenderType"="Opaque" "Queue" = "Transparent+1"}LOD 100Pass{//因?yàn)槭峭该麝?duì)列,所以要注意混合模式 否則不會(huì)與前一幀進(jìn)行有效的混合哦 Blend SrcAlpha OneMinusSrcAlpha//背面的應(yīng)該先渲染 所以先剔除正面Cull FrontCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"struct a2v{float4 vertex : POSITION;float2 texcoord0 : TEXCOORD0;float2 texcoord1 : TEXCOORD1;float2 texcoord2 : TEXCOORD2;float2 texcoord3 : TEXCOORD3;half3 normal : NORMAL;//實(shí)例化需要用到的UNITY宏UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{float2 uv0 : TEXCOORD0;float2 uv1 : TEXCOORD1;float2 uv2 : TEXCOORD2;float2 uv3 : TEXCOORD3;float4 pos : SV_POSITION;float4 posWS : TEXCOORD5;float4 scrPos : TEXCOORD6;half3 normalWS : TEXCOORD4;float newVertexPos : TEXCOORD7;float3 newVertPos : TEXCOORD8;//實(shí)例化需要用到的UNITY宏UNITY_VERTEX_INPUT_INSTANCE_IDUNITY_VERTEX_OUTPUT_STEREO};sampler2D _EdgeMask;float4 _EdgeMask_ST; sampler2D _NoiseMap;float4 _NoiseMap_ST; sampler2D _BeeNoiseMap;float4 _BeeNoiseMap_ST;float4 _EdgeColor;float4 _rimColor;float _rimSmooth;float _rimStrenth;float _ShieldEdgeSmooth;float _ShieldEdgePow;float4 _BeeColor;sampler2D _rampmap;float4 _WaveColor;float _WaveNoiseIntensity;float _FadeScale ;float _FadeSmoosth ;float _FadeIntensity ;float _OffsetDistance;float _OffsetWidth;float4 _NewVertexColor;float _Gloss;float4 _specularColor;sampler2D _FlowMap;float4 _FlowMap_ST; sampler2D _FlowLightMap;float4 _FlowLightMap_ST;float4 _FlowIntensityDirectional;float4 _FlowColor;float _FlowSpeed;float4 _DistortionColor;float _NoiseIntensityDistor;float _DistortionFactor;float _DistortionSmooth;float3 _PositionOffset;//這3個(gè)參數(shù)時(shí)要傳進(jìn)來(lái)的float MaxParticle;float waveSize[100];float4 circleCenter[100];//這3個(gè)參數(shù)時(shí)要傳進(jìn)來(lái)的//聲明深度圖,拿到深度圖算邊界UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);float4 _CameraDepthTexture_TexelSize;//三平面映射 為的是讓沖擊波更好的能映射到模型表面 不受UV影響half4 TriPlanarnotime (float3 posWS,half3 normal,float smooth,sampler2D textures,float2 flow,float2 uv){half3 normalWS = normalize(normal);half3 weight = pow(abs(normalWS),smooth);//就是一個(gè)平均算法 記下就好了half3 uvWeight = weight /(weight.x+weight.y+weight.z);//flow是flowmap的干擾 可以要可以不要 *uv值 是為了做tiling縮放 其實(shí)可以不用half4 col0 = tex2D(textures,posWS.xy*uv+flow)*uvWeight.z;half4 col1 = tex2D(textures,posWS.xz*uv+flow)*uvWeight.y;half4 col2 = tex2D(textures,posWS.zy*uv+flow)*uvWeight.x;return col0+col1+col2;}//FlowMaphalf4 FlowMapFunction (float4 posws,float2 uv,float2 uv2,half Wave){//先算個(gè)時(shí)間float2 timeDelta = frac(_Time.y*_FlowSpeed)*_FlowIntensityDirectional;//再算個(gè)間隔幀時(shí)間float2 timeNext =frac(_Time.y*_FlowSpeed+0.5)*_FlowIntensityDirectional;//再算個(gè)兩個(gè)時(shí)間插值的插值因子float timeLerp = abs(frac(_Time.y*_FlowSpeed)*2-1);half2 flowDirection = 0.5-tex2D(_FlowMap,uv*_FlowMap_ST.xy+_FlowMap_ST.zw).rg+Wave;//前一狀態(tài)的流動(dòng)效果half2 FlowMap = flowDirection*timeDelta;half4 mainTexpre = tex2D(_FlowLightMap,uv*_FlowLightMap_ST.xy+_FlowLightMap_ST.zw+FlowMap);//后一狀態(tài)的流動(dòng)效果half2 flowMapNext = flowDirection*timeNext; half4 mainTex = tex2D(_FlowLightMap,uv*_FlowLightMap_ST.xy+_FlowLightMap_ST.zw+flowMapNext);//插值兩個(gè)流動(dòng)效果 減少頓挫感half4 col = lerp(mainTexpre,mainTex,timeLerp);//做個(gè)MASK 是為了遮擋UV拉伸的地方float mask = 1-saturate(pow(1-smoothstep(uv2.y,1,0.98),1));col *= mask;//輸出最終效果return col; }//計(jì)算可以驅(qū)動(dòng)整塊多邊形進(jìn)行頂點(diǎn)動(dòng)畫(huà)的方法float3 VertexToFaceCenterFirst (float3 worldPos,float3 normalWS){//利用模型中心點(diǎn),頂點(diǎn)法線 等數(shù)據(jù)算出頂點(diǎn)到多邊形面中心點(diǎn)的向量,以此來(lái)移動(dòng)頂點(diǎn)到模型法向量的中心點(diǎn)位置 //從而使得多邊形的頂點(diǎn)能夠統(tǒng)一朝一個(gè)方向變化float3 centerPositionWS = mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;float3 comparePositionWS = worldPos - centerPositionWS;//Rejection 算法float3 newPos = comparePositionWS -normalWS* dot(comparePositionWS,normalWS)/dot(normalWS,normalWS); return newPos;}float3 VertexToFaceCenter (float3 worldPos,float3 normalWS){//利用模型中心點(diǎn),頂點(diǎn)法線 等數(shù)據(jù)算出頂點(diǎn)到多邊形面中心點(diǎn)的向量,以此來(lái)移動(dòng)頂點(diǎn)到模型法向量的中心點(diǎn)位置 //從而使得多邊形的頂點(diǎn)能夠統(tǒng)一朝一個(gè)方向變化float3 temp = VertexToFaceCenterFirst (worldPos,normalWS);float3 newVertexPosition = worldPos.xyz -temp;return newVertexPosition;}//點(diǎn)擊沖擊波,這個(gè)直接copy上個(gè)筆記內(nèi)容的東西half FinalWave (float3 worldPos,float2 uv){half ramp;for (int j = 0; j<MaxParticle; j++){//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//1 大概思路就是先求點(diǎn)擊生成粒子穿過(guò)來(lái)的沖擊波范圍的圓形大小,用世界坐標(biāo)點(diǎn)來(lái)算. |//2 利用粒子傳過(guò)來(lái)的大小來(lái)算出這個(gè)圓形區(qū)域內(nèi)形成的沖擊波的基本圈兒 |//3 再利用一個(gè)參數(shù)模擬一下淡出淡入的效果. 與算平滑的方法一樣 用除法 由于淡入其實(shí)是從小到大的縮放 并且很快速 所以這里相當(dāng)于只是做了淡出效果 |//4 最后看需求是否添加一個(gè)貼圖來(lái)影響一下剛求出的這個(gè)圈兒的外形 當(dāng)然 噪聲圖和三平面映射也都是看情況加 |//5 需要注意的是,由于C#腳本傳進(jìn)來(lái)的是兩個(gè)數(shù)組,所以需要用for循環(huán)來(lái)遍歷每個(gè)數(shù)組里的位置和大小信息, 才能讓生成的每個(gè)粒子的信息 生成所有的像素 C#要傳數(shù)組進(jìn)來(lái) 這個(gè)還得去研究理解下. |//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//求距離 函數(shù)作用是求空間中任意一點(diǎn)到物體表面的最小距離。此間我們假設(shè)坐標(biāo)原點(diǎn)為000中心點(diǎn)//中心點(diǎn)到任意一點(diǎn)像素的最小距離可有如下兩個(gè)函數(shù)求出. 任意一點(diǎn)越接近000點(diǎn)則返回值越小越黑.減去半徑后則可以求畫(huà)出相應(yīng)的圓形.//float dis = length(circleCenter - i.posWS.xyz);float dis = distance(circleCenter[j],worldPos);//再用dis - 傳進(jìn)來(lái)的粒子大小,得到一個(gè)圈兒的大小float circleSize = dis - waveSize[j];float noisemap = tex2D(_NoiseMap, uv).r;//三平面映射方法調(diào)用 如果需要調(diào)用flowmap 則還要給方法增加參數(shù) 這里先不用//float noisemap = TriPlanarnotime(worldPos,normal,0.5,noise,0,uv2).r;//淡出范圍和淡出平滑 float fadesize =1- dis /_FadeScale;float fadeSmooth =saturate( fadesize * _FadeIntensity);//以上內(nèi)容今后看可能就不理解了. 那就操作一遍 一行一行return輸出看過(guò)程float circleCol = saturate((circleSize + noisemap*_WaveNoiseIntensity)/_FadeSmoosth);float wave = tex2D (_rampmap,float2(circleCol,0.5)).r;float wavefade = wave *fadeSmooth;ramp += wavefade;}return clamp(0,1,ramp);}//計(jì)算texLOD的點(diǎn)擊沖擊波函數(shù) 用于頂點(diǎn)著色器中half FinalWaveVertex (float3 worldPos,float smooth,float2 uv2){half ramp;for (int j = 0; j<MaxParticle; j++){//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//1 大概思想就是先求點(diǎn)擊生成粒子穿過(guò)來(lái)的沖擊波范圍的圓形大小,用世界坐標(biāo)點(diǎn)來(lái)算. |//2 利用粒子傳過(guò)來(lái)的大小來(lái)算出這個(gè)圓形區(qū)域內(nèi)形成的沖擊波的基本圈兒 |//3 再利用一個(gè)參數(shù)模擬一下淡出淡入的效果. 與算平滑的方法一樣 用除法 由于淡入其實(shí)是從小到大的縮放 并且很快速 所以這里相當(dāng)于只是做了淡出效果 |//4 最后看需求是否添加一個(gè)貼圖來(lái)影響一下剛求出的這個(gè)圈兒的外形 當(dāng)然 噪聲圖和三平面映射也都是看情況加 |//5 需要注意的是,由于C#腳本傳進(jìn)來(lái)的是兩個(gè)數(shù)組,所以需要用for循環(huán)來(lái)遍歷每個(gè)數(shù)組里的位置和大小信息, 才能讓生成的每個(gè)粒子的信息 生成所有的像素 C#要傳數(shù)組進(jìn)來(lái) 這個(gè)還得去研究理解下. |//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//求距離 函數(shù)作用是求空間中任意一點(diǎn)到物體表面的最小距離。此間我們假設(shè)坐標(biāo)原點(diǎn)為000中心點(diǎn)//中心點(diǎn)到任意一點(diǎn)像素的最小距離可有如下兩個(gè)函數(shù)求出. 任意一點(diǎn)越接近000點(diǎn)則返回值越小越黑.減去半徑后則可以求畫(huà)出相應(yīng)的圓形.//float dis = length(circleCenter - i.posWS.xyz);float dis = distance(circleCenter[j],worldPos);//再用dis - 傳進(jìn)來(lái)的粒子大小,得到一個(gè)圈兒的大小float circleSize = dis - waveSize[j];float noisemap = tex2Dlod(_NoiseMap, float4(uv2,0,0)).r;//三平面映射方法調(diào)用 如果需要調(diào)用flowmap 則還要給方法增加參數(shù) 這里先不用//float noisemap = TriPlanarlod(worldPos,normal,0.5,noise,0,uv2).r;//淡出范圍和淡出平滑 float fadesize =1- dis /_FadeScale;float fadeSmooth =saturate( fadesize * _FadeIntensity);float circleCol = saturate((circleSize + noisemap*_WaveNoiseIntensity*0.2)/smooth);float wave = tex2Dlod (_rampmap,float4(circleCol,0.5,0,0)).r;float wavefade = wave *fadeSmooth;ramp += wavefade;}return saturate(ramp);}//溶解算法 重新定義函數(shù) 用于頂點(diǎn)著色器 溶解時(shí)縮放多邊形half DistortionFunction (float3 newWorldPos,float2 uv){//先算出球體中心點(diǎn)的相對(duì)位置 用頂點(diǎn)世界坐標(biāo) 減去 模型中心點(diǎn)的世界坐標(biāo)空間下的位置 模型中心點(diǎn)一般在DCC軟件里居中 也就是000點(diǎn)的位置 點(diǎn)的位置有意義不是矢量 所以W值為1float3 centerpos =newWorldPos - mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;//傳入溶解起始點(diǎn)位置 float3 localPos = _PositionOffset;//計(jì)算一個(gè)動(dòng)畫(huà)的noise干擾half distortionNoise = tex2Dlod(_NoiseMap,float4(uv+_Time.y*0.05,0,0)).r*_NoiseIntensityDistor;//通過(guò)distance函數(shù) 算出溶解黑白遮罩范圍half dispos = distance(centerpos,localPos);//再用范圍減去一個(gè)值算出邊界 減去noise干擾值 增加擾動(dòng)效果 最后除以一個(gè)值來(lái)控制溶解變寬的平滑過(guò)渡范圍half distortion = saturate((dispos - _DistortionFactor-distortionNoise)/_DistortionSmooth);return distortion;}v2f vert (a2v v){v2f o;//實(shí)例化需要用到的UNITY宏UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);UNITY_TRANSFER_INSTANCE_ID(v,o);o.normalWS = (UnityObjectToWorldNormal(v.normal));o.posWS = mul(unity_ObjectToWorld,v.vertex);o.uv0 = v.texcoord0;o.uv1 = v.texcoord1;o.uv2 = v.texcoord2;o.uv3 = v.texcoord3;//計(jì)算點(diǎn)擊效果對(duì)頂點(diǎn)的偏移影響//算出點(diǎn)擊的中心點(diǎn)位置float3 newVertexPositionWS = VertexToFaceCenter(o.posWS.xyz,o.normalWS);//算出此位置下點(diǎn)擊對(duì)頂點(diǎn)的位移變化值half waveVertex = FinalWaveVertex (newVertexPositionWS,_OffsetWidth,o.uv2);//溶解頂點(diǎn)縮放float3 newVertPosCenter = VertexToFaceCenterFirst(o.posWS,o.normalWS);half distortionVertex = DistortionFunction(newVertexPositionWS,o.uv2);//用負(fù)號(hào)做個(gè)反向,來(lái)表示出現(xiàn)消失的正負(fù)方向float3 distortionNewPos = -distortionVertex*newVertPosCenter+o.posWS.xyz;//再將頂點(diǎn)溶解轉(zhuǎn)換到模型空間下 好做相對(duì)位置的位移縮放float3 localDistiortion = mul (unity_WorldToObject,distortionNewPos);//用算好的偏移值 去在他的法線方向上做擾動(dòng)。 這里注意對(duì)法線擾動(dòng)是用乘法來(lái)做 與outline的xy軸做乘法計(jì)算是一樣的 然后把擾動(dòng)值 作為頂點(diǎn)偏移值 累加到vertex上v.normal *= waveVertex*0.01;//這一步就是相當(dāng)于把頂點(diǎn)按照法線方向外拓 也就是按照發(fā)現(xiàn)方向位移float3 newVertex =v.vertex.xyz+v.normal*_OffsetDistance+localDistiortion;//因?yàn)橹岸际窃谙鄬?duì)坐標(biāo)下進(jìn)行 所以要再減去原本的頂點(diǎn)坐標(biāo) 來(lái)轉(zhuǎn)換成絕對(duì)坐標(biāo) 原理同世界空間坐標(biāo) 減去 模型頂點(diǎn)自身坐標(biāo)在世界空間下的表示一樣 以防止起始位置會(huì)隨模型移動(dòng)而相對(duì)于模型本身位置發(fā)生改變newVertex -=v.vertex.xyz;//最后再把相應(yīng)的計(jì)算結(jié)果存到插槽中 傳到片元著色器o.pos = UnityObjectToClipPos(newVertex);o.scrPos = ComputeScreenPos(o.pos);o.newVertexPos = waveVertex;o.newVertPos = newVertexPositionWS;return o;}half4 frag (v2f i) : SV_Target{//點(diǎn)擊釋放沖擊波 half wave = saturate(FinalWave (i.posWS , i.uv3));//給沖擊波加個(gè)顏色 half4 waveCol = wave *_WaveColor;//把受頂點(diǎn)動(dòng)畫(huà)影響的片也進(jìn)行著色 最后加到最終結(jié)果中half4 newVertexColor = i.newVertexPos*_NewVertexColor;//多邊形遮罩half beeTex = tex2D(_EdgeMask,i.uv0).r;//噪聲擾動(dòng)圖half beeNoise=tex2D(_BeeNoiseMap,i.uv3*_BeeNoiseMap_ST.xy+_BeeNoiseMap_ST.zw*_Time.y*0.01);//把噪聲一加完成half4 beeColor = beeTex*_EdgeColor+beeTex*beeNoise*_BeeColor;//求交叉邊緣 這一套亂七八糟的操作 只能背了//除以分量w來(lái)得到屏幕空間的頂點(diǎn)坐標(biāo)位置float4 screenPos = i.scrPos/i.scrPos.w;//這里需要做個(gè)近裁剪面的正負(fù)值判斷 來(lái)修正Z值screenPos.z = UNITY_NEAR_CLIP_VALUE>=0 ? screenPos.z : screenPos.z*0.5+0.5;//利用屏幕空間中XY坐標(biāo)也就是像素位置來(lái)采樣深度圖 得到實(shí)際深度值float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,screenPos.xy));//這步推測(cè)是為了根據(jù)深度值在屏幕空間下的交叉邊界的像體現(xiàn)float distanceDepth =saturate(abs((depth - LinearEyeDepth(screenPos.z))));//然后根據(jù)結(jié)果算出邊界的和非邊界的地方. 這里這么計(jì)算總覺(jué)得就把平滑過(guò)渡的計(jì)算給干掉了 氣氛上感覺(jué)還要除以一個(gè)smooth值 所以我擅自加上看看float EdgeSmooth =(1-saturate(smoothstep(0,_ShieldEdgePow,distanceDepth)))/_ShieldEdgeSmooth;//溶解float3 centerpos =i.newVertPos - mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;float3 localPos = _PositionOffset;//用uv2 來(lái)模擬閃爍效果half distortionNoise = tex2D(_NoiseMap,i.uv2+_Time.y*0.05).r*_NoiseIntensityDistor;half dispos = distance(localPos,centerpos);half distortion = saturate((dispos - _DistortionFactor+distortionNoise)/_DistortionSmooth);half distortionStep = step(0,saturate((dispos - _DistortionFactor+distortionNoise)));half4 distorCol = (distortion+distortion*distortionStep)*_DistortionColor;//邊緣光 NV 計(jì)算 要復(fù)雜點(diǎn)的話就用 shlick的 近似公式來(lái)計(jì)算//shlick近似等式 為 fresnel = f0 +(1-f0)*pow(1-NV,5);half3 viewDir = normalize(UnityWorldSpaceViewDir(i.posWS));half3 normalDir = normalize(i.normalWS);half3 lightDir = normalize(UnityWorldSpaceLightDir(i.posWS));half NV = abs(dot(viewDir,normalDir));//把邊緣交叉的部分算邊緣光里 half rimArea = saturate(1 - NV);half4 rimColor =saturate(((rimArea+EdgeSmooth)+_rimStrenth)/_rimSmooth)*_rimColor;//再加個(gè)表面高光吧 看起來(lái)可能更精致點(diǎn)half3 Hdir = normalize(viewDir+lightDir);half NH = saturate(dot(normalDir,Hdir));half spec = abs(pow(NH,_Gloss));half4 speccolor = spec*_specularColor;//護(hù)盾流動(dòng)FlowMaphalf2 flowDirectionalIntensity = _FlowIntensityDirectional.xy;half4 FlowMapColor = FlowMapFunction(i.posWS,i.uv3,i.uv3,wave)*_FlowColor; half4 finalCol = rimColor+beeColor+FlowMapColor+waveCol+newVertexColor+speccolor;//溶解邊緣光插值合并//beeColor.rgb*4 為個(gè)人調(diào)整亮度值的經(jīng)驗(yàn)系數(shù)half3 col = lerp(finalCol.rgb,distorCol.rgb+distorCol.rgb*beeTex*beeColor.rgb*4,saturate(distortion));//Alpha計(jì)算 在透明物體計(jì)算的過(guò)程中 尤為重要 不要搞錯(cuò)最終輸出的alpha值到底會(huì)受到哪些方面的影響half finalAlpha =saturate(1-distortion)*finalCol.a;//將這個(gè)pass由于是先剔除正面的 放在背面渲染 所以亮度相對(duì)降低一點(diǎn),做出點(diǎn)前后層次感 0.65也是一個(gè)經(jīng)驗(yàn)值 所以計(jì)算在內(nèi) 也可以直接給finalAlpha值進(jìn)行一個(gè)縮小return float4(col*0.65,finalAlpha);}ENDCG}Pass{Blend SrcAlpha OneMinusSrcAlphaCull BackCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"struct a2v{float4 vertex : POSITION;float2 texcoord0 : TEXCOORD0;float2 texcoord1 : TEXCOORD1;float2 texcoord2 : TEXCOORD2;float2 texcoord3 : TEXCOORD3;half3 normal : NORMAL;//實(shí)例化需要用到的UNITY宏UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{float2 uv0 : TEXCOORD0;float2 uv1 : TEXCOORD1;float2 uv2 : TEXCOORD2;float2 uv3 : TEXCOORD3;float4 pos : SV_POSITION;float4 posWS : TEXCOORD5;float4 scrPos : TEXCOORD6;half3 normalWS : TEXCOORD4;float newVertexPos : TEXCOORD7;float3 newVertPos : TEXCOORD8;//實(shí)例化需要用到的UNITY宏UNITY_VERTEX_INPUT_INSTANCE_IDUNITY_VERTEX_OUTPUT_STEREO};sampler2D _EdgeMask;float4 _EdgeMask_ST; sampler2D _NoiseMap;float4 _NoiseMap_ST; sampler2D _BeeNoiseMap;float4 _BeeNoiseMap_ST;float4 _EdgeColor;float4 _rimColor;float _rimSmooth;float _rimStrenth;float _ShieldEdgeSmooth;float _ShieldEdgePow;float4 _BeeColor;sampler2D _rampmap;float4 _WaveColor;float _WaveNoiseIntensity;float _FadeScale ;float _FadeSmoosth ;float _FadeIntensity ;float _OffsetDistance;float _OffsetWidth;float4 _NewVertexColor;float _Gloss;float4 _specularColor;sampler2D _FlowMap;float4 _FlowMap_ST; sampler2D _FlowLightMap;float4 _FlowLightMap_ST;float4 _FlowIntensityDirectional;float4 _FlowColor;float _FlowSpeed;float4 _DistortionColor;float _NoiseIntensityDistor;float _DistortionFactor;float _DistortionSmooth;float3 _PositionOffset;//這3個(gè)參數(shù)時(shí)要傳進(jìn)來(lái)的float MaxParticle;float waveSize[100];float4 circleCenter[100];//這3個(gè)參數(shù)時(shí)要傳進(jìn)來(lái)的//聲明深度圖,拿到深度圖算邊界UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);float4 _CameraDepthTexture_TexelSize;//三平面映射 為的是讓沖擊波更好的能映射到模型表面 不受UV影響half4 TriPlanarnotime (float3 posWS,half3 normal,float smooth,sampler2D textures,float2 flow,float2 uv){half3 normalWS = normalize(normal);half3 weight = pow(abs(normalWS),smooth);half3 uvWeight = weight /(weight.x+weight.y+weight.z);//flow是flowmap的干擾 可以要可以不要 *uv值 是為了做tiling縮放 其實(shí)可以不用half4 col0 = tex2D(textures,posWS.xy*uv+flow)*uvWeight.z;half4 col1 = tex2D(textures,posWS.xz*uv+flow)*uvWeight.y;half4 col2 = tex2D(textures,posWS.zy*uv+flow)*uvWeight.x;return col0+col1+col2;}//FlowMaphalf4 FlowMapFunction (float4 posws,float2 uv,float2 uv2,half Wave){//先算個(gè)時(shí)間float2 timeDelta = frac(_Time.y*_FlowSpeed)*_FlowIntensityDirectional;//再算個(gè)間隔幀時(shí)間float2 timeNext =frac(_Time.y*_FlowSpeed+0.5)*_FlowIntensityDirectional;//再算個(gè)兩個(gè)時(shí)間插值的插值因子float timeLerp = abs(frac(_Time.y*_FlowSpeed)*2-1);half2 flowDirection = 0.5-tex2D(_FlowMap,uv*_FlowMap_ST.xy+_FlowMap_ST.zw).rg+Wave;//前一狀態(tài)的流動(dòng)效果half2 FlowMap = flowDirection*timeDelta;half4 mainTexpre = tex2D(_FlowLightMap,uv*_FlowLightMap_ST.xy+_FlowLightMap_ST.zw+FlowMap);//后一狀態(tài)的流動(dòng)效果half2 flowMapNext = flowDirection*timeNext; half4 mainTex = tex2D(_FlowLightMap,uv*_FlowLightMap_ST.xy+_FlowLightMap_ST.zw+flowMapNext);//插值兩個(gè)流動(dòng)效果 減少頓挫感half4 col = lerp(mainTexpre,mainTex,timeLerp);float mask = 1-saturate(pow(1-smoothstep(uv2.y,1,0.98),1));col *= mask;//輸出最終效果return col; }//計(jì)算可以驅(qū)動(dòng)整塊多邊形進(jìn)行頂點(diǎn)動(dòng)畫(huà)的方法float3 VertexToFaceCenterFirst (float3 worldPos,float3 normalWS){//利用模型中心點(diǎn),頂點(diǎn)法線 等數(shù)據(jù)算出頂點(diǎn)到多邊形面中心點(diǎn)的向量,以此來(lái)移動(dòng)頂點(diǎn)到模型法向量的中心點(diǎn)位置 //從而使得多邊形的頂點(diǎn)能夠統(tǒng)一朝一個(gè)方向變化float3 centerPositionWS = mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;float3 comparePositionWS = worldPos - centerPositionWS;float3 newPos = comparePositionWS -normalWS* dot(comparePositionWS,normalWS)/dot(normalWS,normalWS); return newPos;}float3 VertexToFaceCenter (float3 worldPos,float3 normalWS){//利用模型中心點(diǎn),頂點(diǎn)法線 等數(shù)據(jù)算出頂點(diǎn)到多邊形面中心點(diǎn)的向量,以此來(lái)移動(dòng)頂點(diǎn)到模型法向量的中心點(diǎn)位置 //從而使得多邊形的頂點(diǎn)能夠統(tǒng)一朝一個(gè)方向變化float3 temp = VertexToFaceCenterFirst (worldPos,normalWS);float3 newVertexPosition = worldPos.xyz -temp;return newVertexPosition;}//點(diǎn)擊沖擊波,這個(gè)直接copy原來(lái)的half FinalWave (float3 worldPos,float2 uv){half ramp;for (int j = 0; j<MaxParticle; j++){//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//1 大概思路就是先求點(diǎn)擊生成粒子穿過(guò)來(lái)的沖擊波范圍的圓形大小,用世界坐標(biāo)點(diǎn)來(lái)算. |//2 利用粒子傳過(guò)來(lái)的大小來(lái)算出這個(gè)圓形區(qū)域內(nèi)形成的沖擊波的基本圈兒 |//3 再利用一個(gè)參數(shù)模擬一下淡出淡入的效果. 與算平滑的方法一樣 用除法 由于淡入其實(shí)是從小到大的縮放 并且很快速 所以這里相當(dāng)于只是做了淡出效果 |//4 最后看需求是否添加一個(gè)貼圖來(lái)影響一下剛求出的這個(gè)圈兒的外形 當(dāng)然 噪聲圖和三平面映射也都是看情況加 |//5 需要注意的是,由于C#腳本傳進(jìn)來(lái)的是兩個(gè)數(shù)組,所以需要用for循環(huán)來(lái)遍歷每個(gè)數(shù)組里的位置和大小信息, 才能讓生成的每個(gè)粒子的信息 生成所有的像素 C#要傳數(shù)組進(jìn)來(lái) 這個(gè)還得去研究理解下. |//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//求距離 函數(shù)作用是求空間中任意一點(diǎn)到物體表面的最小距離。此間我們假設(shè)坐標(biāo)原點(diǎn)為000中心點(diǎn)//中心點(diǎn)到任意一點(diǎn)像素的最小距離可有如下兩個(gè)函數(shù)求出. 任意一點(diǎn)越接近000點(diǎn)則返回值越小越黑.減去半徑后則可以求畫(huà)出相應(yīng)的圓形.//float dis = length(circleCenter - i.posWS.xyz);float dis = distance(circleCenter[j],worldPos);//再用dis - 傳進(jìn)來(lái)的粒子大小,得到一個(gè)圈兒的大小float circleSize = dis - waveSize[j];float noisemap = tex2D(_NoiseMap, uv).r;//三平面映射方法調(diào)用 如果需要調(diào)用flowmap 則還要給方法增加參數(shù) 這里先不用//float noisemap = TriPlanarnotime(worldPos,normal,0.5,noise,0,uv2).r;//淡出范圍和淡出平滑 float fadesize =1- dis /_FadeScale;float fadeSmooth =saturate( fadesize * _FadeIntensity);float circleCol = saturate((circleSize + noisemap*_WaveNoiseIntensity)/_FadeSmoosth);float wave = tex2D (_rampmap,float2(circleCol,0.5)).r;float wavefade = wave *fadeSmooth;ramp += wavefade;}return clamp(0,1,ramp);}//計(jì)算texLOD的點(diǎn)擊沖擊波函數(shù) 用于頂點(diǎn)著色器中half FinalWaveVertex (float3 worldPos,float smooth,float2 uv2){half ramp;for (int j = 0; j<MaxParticle; j++){//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//1 大概思想就是先求點(diǎn)擊生成粒子穿過(guò)來(lái)的沖擊波范圍的圓形大小,用世界坐標(biāo)點(diǎn)來(lái)算. |//2 利用粒子傳過(guò)來(lái)的大小來(lái)算出這個(gè)圓形區(qū)域內(nèi)形成的沖擊波的基本圈兒 |//3 再利用一個(gè)參數(shù)模擬一下淡出淡入的效果. 與算平滑的方法一樣 用除法 由于淡入其實(shí)是從小到大的縮放 并且很快速 所以這里相當(dāng)于只是做了淡出效果 |//4 最后看需求是否添加一個(gè)貼圖來(lái)影響一下剛求出的這個(gè)圈兒的外形 當(dāng)然 噪聲圖和三平面映射也都是看情況加 |//5 需要注意的是,由于C#腳本傳進(jìn)來(lái)的是兩個(gè)數(shù)組,所以需要用for循環(huán)來(lái)遍歷每個(gè)數(shù)組里的位置和大小信息, 才能讓生成的每個(gè)粒子的信息 生成所有的像素 C#要傳數(shù)組進(jìn)來(lái) 這個(gè)還得去研究理解下. |//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//求距離 函數(shù)作用是求空間中任意一點(diǎn)到物體表面的最小距離。此間我們假設(shè)坐標(biāo)原點(diǎn)為000中心點(diǎn)//中心點(diǎn)到任意一點(diǎn)像素的最小距離可有如下兩個(gè)函數(shù)求出. 任意一點(diǎn)越接近000點(diǎn)則返回值越小越黑.減去半徑后則可以求畫(huà)出相應(yīng)的圓形.//float dis = length(circleCenter - i.posWS.xyz);float dis = distance(circleCenter[j],worldPos);//再用dis - 傳進(jìn)來(lái)的粒子大小,得到一個(gè)圈兒的大小float circleSize = dis - waveSize[j];float noisemap = tex2Dlod(_NoiseMap, float4(uv2,0,0)).r;//三平面映射方法調(diào)用 如果需要調(diào)用flowmap 則還要給方法增加參數(shù) 這里先不用//float noisemap = TriPlanarlod(worldPos,normal,0.5,noise,0,uv2).r;//淡出范圍和淡出平滑 float fadesize =1- dis /_FadeScale;float fadeSmooth =saturate( fadesize * _FadeIntensity);float circleCol = saturate((circleSize + noisemap*_WaveNoiseIntensity*0.2)/smooth);float wave = tex2Dlod (_rampmap,float4(circleCol,0.5,0,0)).r;float wavefade = wave *fadeSmooth;ramp += wavefade;}return saturate(ramp);}//溶解算法 重新定義函數(shù) 用于頂點(diǎn)著色器 溶解時(shí)縮放多邊形half DistortionFunction (float3 newWorldPos,float2 uv){float3 centerpos =newWorldPos - mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;float3 localPos = _PositionOffset;half distortionNoise = tex2Dlod(_NoiseMap,float4(uv+_Time.y*0.05,0,0)).r*_NoiseIntensityDistor;half dispos = distance(centerpos,localPos);half distortion = saturate((dispos - _DistortionFactor-distortionNoise)/_DistortionSmooth);return distortion;}v2f vert (a2v v){v2f o;//實(shí)例化需要用到的UNITY宏UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);UNITY_TRANSFER_INSTANCE_ID(v,o);o.normalWS = (UnityObjectToWorldNormal(v.normal));o.posWS = mul(unity_ObjectToWorld,v.vertex);o.uv0 = v.texcoord0;o.uv1 = v.texcoord1;o.uv2 = v.texcoord2;o.uv3 = v.texcoord3;//計(jì)算點(diǎn)擊效果對(duì)頂點(diǎn)的偏移影響float3 newVertexPositionWS = VertexToFaceCenter(o.posWS.xyz,o.normalWS);half waveVertex = FinalWaveVertex (newVertexPositionWS,_OffsetWidth,o.uv2);//溶解頂點(diǎn)縮放float3 newVertPosCenter = VertexToFaceCenterFirst(o.posWS,o.normalWS);half distortionVertex = DistortionFunction(newVertexPositionWS,o.uv2);float3 distortionNewPos = -distortionVertex*newVertPosCenter+o.posWS.xyz;float3 localDistiortion = mul (unity_WorldToObject,distortionNewPos);//用算好的偏移值 去在他的法線方向上做擾動(dòng)。 然后把擾動(dòng)值 作為頂點(diǎn)偏移值 累加到vertex上v.normal *= waveVertex*0.01;float3 newVertex =v.vertex.xyz+v.normal*_OffsetDistance+localDistiortion;newVertex -=v.vertex.xyz;o.pos = UnityObjectToClipPos(newVertex);o.scrPos = ComputeScreenPos(o.pos);o.newVertexPos = waveVertex;o.newVertPos = newVertexPositionWS;return o;}half4 frag (v2f i) : SV_Target{//點(diǎn)擊釋放沖擊波 half wave = saturate(FinalWave (i.posWS , i.uv3));half4 waveCol = wave *_WaveColor;//把受頂點(diǎn)動(dòng)畫(huà)影響的片也進(jìn)行著色 最后加到最終結(jié)果中half4 newVertexColor = i.newVertexPos*_NewVertexColor;//多邊形遮罩half beeTex = tex2D(_EdgeMask,i.uv0).r;//噪聲擾動(dòng)圖half beeNoise=tex2D(_BeeNoiseMap,i.uv3*_BeeNoiseMap_ST.xy+_BeeNoiseMap_ST.zw*_Time.y*0.01);//把噪聲一加完成half4 beeColor = beeTex*_EdgeColor+beeTex*beeNoise*_BeeColor;//求交叉邊緣 float4 screenPos = i.scrPos/i.scrPos.w;screenPos.z = UNITY_NEAR_CLIP_VALUE>=0 ? screenPos.z : screenPos.z*0.5+0.5;float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,screenPos.xy));float distanceDepth =saturate(abs((depth - LinearEyeDepth(screenPos.z))));float EdgeSmooth =(1-saturate(smoothstep(0,_ShieldEdgePow,distanceDepth)))/_ShieldEdgeSmooth;//溶解float3 centerpos =i.newVertPos - mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz;float3 localPos = _PositionOffset;//用uv2 來(lái)模擬閃爍效果half distortionNoise = tex2D(_NoiseMap,i.uv2+_Time.y*0.05).r*_NoiseIntensityDistor;half dispos = distance(localPos,centerpos);half distortion = saturate((dispos - _DistortionFactor+distortionNoise)/_DistortionSmooth);half distortionStep = step(0,saturate((dispos - _DistortionFactor+distortionNoise)));half4 distorCol = (distortion+distortion*distortionStep)*_DistortionColor;//邊緣光 NV 計(jì)算 要復(fù)雜點(diǎn)的話就用 shlick的 近似公式來(lái)計(jì)算//shlick近似等式 為 fresnel = f0 +(1-f0)*pow(1-NV,5);half3 viewDir = normalize(UnityWorldSpaceViewDir(i.posWS));half3 normalDir = normalize(i.normalWS);half3 lightDir = normalize(UnityWorldSpaceLightDir(i.posWS));half NV = abs(dot(viewDir,normalDir));//把邊緣交叉的部分算邊緣光里 half rimArea = saturate(1 - NV);half4 rimColor =saturate(((rimArea+EdgeSmooth)+_rimStrenth)/_rimSmooth)*_rimColor;//再加個(gè)表面高光吧 看起來(lái)可能更精致點(diǎn)half3 Hdir = normalize(viewDir+lightDir);half NH = saturate(dot(normalDir,Hdir));half spec = abs(pow(NH,_Gloss));half4 speccolor = spec*_specularColor;//護(hù)盾流動(dòng)FlowMaphalf2 flowDirectionalIntensity = _FlowIntensityDirectional.xy;half4 FlowMapColor = FlowMapFunction(i.posWS,i.uv3,i.uv3,wave)*_FlowColor; half4 finalCol = rimColor+beeColor+FlowMapColor+waveCol+newVertexColor+speccolor;//溶解邊緣光插值合并half3 col = lerp(finalCol.rgb,distorCol.rgb+distorCol.rgb*beeTex*beeColor.rgb*4,saturate(distortion));half finalAlpha =saturate(1-distortion)*finalCol.a;return float4(col,finalAlpha);}ENDCG}} }

總結(jié)

其實(shí)在寫(xiě)這個(gè)筆記的時(shí)候,已經(jīng)是做好效果一禮拜之后了。果不其然,很多我都看不懂額。所以重新對(duì)每一行進(jìn)行理解再進(jìn)行注釋。沒(méi)辦法,自己記憶力和腦子越來(lái)越不好。年齡和壓力擺在這兒。只能用這樣的笨辦法強(qiáng)迫自己反復(fù)去記憶理解吧。 雖然現(xiàn)在學(xué)習(xí)進(jìn)度越來(lái)越慢,但我還是不會(huì)放棄的。 加油老男孩兒。

總結(jié)

以上是生活随笔為你收集整理的带顶点动画的护盾效果——UnityShader学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。