作者說
- 本系列教程適用于有編程基礎和圖形學基礎知識的讀者.
- 如果對您有所幫助,請點個免費的贊和關注,您的支持就是我更新最大的動力!
- 如果你有任何想看的內容歡迎評論區留言!
- 本系列教程Github : https://github.com/Sky0Master/Unity-URP-Shader-Tutorial
效果預覽
準備工作
在Unity Assets文件夾里右鍵新建一個Unlit Shader
命名之后,再右鍵這個shader,create -> material
接著隨便把這個材質應用到一個Renderer上就行,我這里應用到了一個Sprite Renderer上
動手寫代碼!
現在我們來實現一個對紋理施加漩渦效果的shader,其實這個效果的原理就是在fragment著色器中對uv坐標進行繞中心旋轉的變換,使用變換后的uv坐標去采樣。(如果對【采樣】和【uv坐標】的概念比較熟悉的話應該能理解
每一行代碼我都進行了詳細的注釋,如果對其中有任何不明白的地方請在評論區留言,我會據此對注釋進行補充,感謝!
Shader "Unlit/SwirlEffect"
{Properties {_MainTex ("Base Texture", 2D) = "white" {} // 基礎紋理輸入,用于最終顏色輸出_Angle ("Rotation Angle", Range(0,10)) = 2 // 控制旋轉強度的參數, Range(0,10)限制調節范圍避免過度扭曲_Radius ("Effect Radius", Range(0,1)) = 0.5 // 效果作用半徑,控制漩渦中心到邊緣的衰減范圍}SubShader{Tags { "RenderType"="Transparent" //著色器替換標簽,這個部分建議參考https://docs.unity3d.com/cn/current/Manual/SL-ShaderReplacement.html"Queue"="Transparent" //設置渲染隊列為透明層級"RenderPipeline"="UniversalPipeline" //聲明使用的渲染管線}Pass{Blend SrcAlpha OneMinusSrcAlpha // 使用標準透明度混合 讀者可以嘗試注釋掉這行會發生什么HLSLPROGRAM //使用URP標準的HLSL語法#pragma vertex vert // 聲明頂點著色器#pragma fragment frag // 聲明片段著色器//#pragma multi_compile_fog //開啟霧效支持//URP專用#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"struct Attributes { //輸入數據結構 (URP命名規范)float4 positionOS : POSITION; //物體空間的頂點坐標float2 uv : TEXCOORD0; //初始紋理坐標};struct Varyings { //輸出數據結構 (URP命名規范)float4 positionCS : SV_POSITION; //裁剪空間坐標(SV_前綴)float2 uv : TEXCOORD0; //傳遞紋理坐標};TEXTURE2D(_MainTex); //在HLSL中,TEXTURE2D是一個宏,用于聲明紋理資源, 這行代碼告訴Shader存在一個名為_MainTex的2D紋理,供后續采樣使用SAMPLER(sampler_MainTex); //SAMPLER宏聲明采樣器狀態,與紋理綁定。URP中,紋理和采樣器通常是分開的,這樣可以更靈活地重用采樣器設置float _Angle; //自定義的屬性,在Properties塊中聲明后,需要在HLSL代碼中再次聲明,以便在著色器中使用. 這樣可以在Properties和HLSL中同步變量,確保參數傳遞正確float _Radius;Varyings vert(Attributes IN) {Varyings OUT;OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz); // URP坐標變換OUT.uv = IN.uv; // 直接傳遞UVreturn OUT;}half4 frag(Varyings IN) : SV_Target {// 計算中心偏移float2 centerOffset = IN.uv - float2(0.5,0.5);float distance = length(centerOffset);// 動態旋轉計算float rotation = _Angle * saturate(1 - distance/_Radius); //基于自定義半徑的衰減計算float sinRot, cosRot; sincos(rotation, sinRot, cosRot); //性能優化,同時計算旋轉角度的sin和cos而不是分開計算// UV變換矩陣float2x2 rotMatrix = float2x2(cosRot, -sinRot, sinRot, cosRot); //旋轉矩陣構造float2 distortedUV = mul(rotMatrix, centerOffset) + 0.5; //應用矩陣變換// 采樣紋理half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, distortedUV); //使用變換后的uv坐標去采樣紋理// 邊緣淡化float fade = smoothstep(_Radius, _Radius * 0.8, distance); //邊緣過渡優化return half4(color.rgb, color.a * fade); //透明度混合}ENDHLSL}}
}