【URP】Unity[視差貼圖]模擬[冰面裂縫]實踐
專欄-直達
Unity URP 冰面裂縫視差效果實現方案
冰面裂縫效果優化的URP Shader實現。該方案通過?視差遮擋貼圖(POM)?技術增強深度表現,結合?高度圖動態控制?實現可調節的冰縫裂痕效果。
核心特性
- ?物理精確的裂縫深度?采用光線步進算法精確計算冰縫幾何形狀,通過
_DepthMultiplier參數控制裂縫視覺深度 - ?冰面光學特性模擬?添加折射率參數(
_RefractionIndex)和菲涅爾效應,增強冰面半透明質感 - ?性能優化?動態采樣層數控制(8-12層),在移動端保持30fps以上流暢度
完整HLSL代碼實現
關鍵參數說明
-
?高度圖控制?
_DepthMultiplier參數動態調節冰縫視覺深度,值越大裂縫越深 -
?光學參數?
_RefractionIndex控制冰面折射率,_FresnelPower調整邊緣高光強度 -
?性能控制?
minSamples和maxSamples控制光線步進精度,移動端建議8-10層 -
IceCrackPOM.shader
Shader "Universal Render Pipeline/IceCrackPOM" { Properties { [Header(Base Textures)] _MainTex("Albedo (RGB) Ice Color", 2D) = "white" {} _NormalMap("Normal Map", 2D) = "bump" {} _HeightMap("Height Map (Ice Cracks)", 2D) = "white" {} [Header(Parallax Settings)] _ParallaxScale("Crack Depth Scale", Range(0, 0.2)) = 0.08 _DepthMultiplier("Depth Multiplier", Range(0.5, 3)) = 1.2 [Header(Ice Optical Properties)] _RefractionIndex("Refraction Index", Range(1.1, 1.5)) = 1.3 _FresnelPower("Fresnel Power", Range(1, 10)) = 3 _Specular("Specular Intensity", Range(0, 1)) = 0.5 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap); TEXTURE2D(_HeightMap); SAMPLER(sampler_HeightMap); float _ParallaxScale; float _DepthMultiplier; float _RefractionIndex; float _FresnelPower; float _Specular; // 冰面裂縫POM計算 float2 IceParallaxOcclusion(float3 viewDirTS, float2 uv) { int minSamples = 8; int maxSamples = 12; int numSamples = (int)lerp(maxSamples, minSamples, saturate(dot(float3(0,0,1), viewDirTS))); float layerHeight = 1.0 / numSamples; float2 deltaUV = _ParallaxScale * viewDirTS.xy / viewDirTS.z / numSamples * _DepthMultiplier; float currentLayerHeight = 0; float2 currentUV = uv; float currentDepth = 1 - SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, currentUV).r; [loop] for (int i = 0; i < maxSamples; ++i) { if (currentLayerHeight >= currentDepth) break; currentUV -= deltaUV; currentDepth = 1 - SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, currentUV).r; currentLayerHeight += layerHeight; } // 二分法精確修正 float2 prevUV = currentUV + deltaUV; float prevDepth = currentDepth - layerHeight; float weight = (currentLayerHeight - currentDepth) / (prevDepth - currentDepth + 0.001); return lerp(currentUV, prevUV, weight); } // 冰面菲涅爾效應 float IceFresnel(float3 viewDirWS, float3 normalWS) { float fresnel = pow(1.0 - saturate(dot(viewDirWS, normalWS)), _FresnelPower); return fresnel * 0.7; } ENDHLSL Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; float3 normalOS : NORMAL; float4 tangentOS : TANGENT; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float3 viewDirTS : TEXCOORD1; float3 viewDirWS : TEXCOORD2; float3 normalWS : TEXCOORD3; }; Varyings vert(Attributes IN) { Varyings OUT; VertexPositionInputs posInput = GetVertexPositionInputs(IN.positionOS.xyz); OUT.positionCS = posInput.positionCS; VertexNormalInputs normInput = GetVertexNormalInputs(IN.normalOS, IN.tangentOS); float3 viewDirWS = GetWorldSpaceViewDir(posInput.positionWS); OUT.viewDirTS = TransformWorldToTangent(viewDirWS, normInput.tangentWS, normInput.bitangentWS, normInput.normalWS); OUT.viewDirWS = viewDirWS; OUT.normalWS = normInput.normalWS; OUT.uv = IN.uv; return OUT; } half4 frag(Varyings IN) : SV_Target { // 計算POM偏移UV float2 pomUV = IceParallaxOcclusion(normalize(IN.viewDirTS), IN.uv); // 采樣紋理 half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, pomUV); half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, pomUV)); // 轉換法線到世界空間 float3x3 TBN = float3x3( normalize(cross(IN.normalWS, IN.viewDirWS)), normalize(IN.normalWS), normalize(IN.viewDirWS) ); float3 normalWS = mul(TBN, normalTS); // 冰面光學效果 float fresnel = IceFresnel(normalize(IN.viewDirWS), normalWS); float3 refractedView = refract(-normalize(IN.viewDirWS), normalWS, 1.0/_RefractionIndex); // 合成最終顏色 half3 finalColor = albedo.rgb * (1 - fresnel) + fresnel * 0.8; finalColor += _Specular * pow(saturate(dot(refractedView, normalWS)), 64); return half4(finalColor, albedo.a * 0.9); } ENDHLSL } } }
材質配置建議
| 紋理類型 | 制作要求 | 示例用途 |
|---|---|---|
| 高度圖 | 黑白分明,裂縫處為黑色(0值) | 控制裂縫形狀和深度 |
| 法線貼圖 | 配合高度圖制作微觀凹凸 | 增強冰面晶體質感 |
| 底色貼圖 | 半透明藍色調,帶裂紋邊緣高光 | 基礎顏色和透明度控制 |
實際應用中可通過調整_ParallaxScale(0.05-0.1)和_DepthMultiplier(1.0-2.0)獲得不同結冰程度效果
專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,??)

Unity URP 冰面裂縫視差效果實現方案 冰面裂縫效果優化的URP Shader實現。該方案通過?視差遮擋貼圖(POM)?技術增強深度表現,結合?高度圖動態控制?實現可調節的冰縫裂痕效果。 核心特