Shader "Custom/ParallaxCloud" { Properties { _MainTex ("BaseMap:基础贴图", 2D) = "white" {} // _TurbulenceTex ("turbulence:扰动图", 2D) = "white" {} _Color ("Color:颜色", Color) = (0.0, 0.0, 0.0, 1.0) _ParallaxSize ("ParallaxSize:视差映射强度", Range(0.0, 0.1)) = 0.0 _ParallaxLayers ("ParallaxLayers:视差映射层数", Range(1.0, 50.0)) = 20 _MoveSpeed ("MoveSpeed:移动速度", Range(-0.5, 0.5)) = 0.1 _Alpha ("Alpha:透明度", Range(0, 1)) = 0.5 _AlphaExtent ("AlphaExtent:透明对比度", Range(0.0, 5.0)) = 5.0 // _worldDis("云的最远距离", float) = 0 _ruiHua("虚化距离", float) = 300 } SubShader { Tags { "RenderPipeline"="UniversalPipeline" "Queue"="Transparent" "RenderType"="Transparent" } Pass { Blend SrcAlpha OneMinusSrcAlpha Cull off ZWrite off HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 uv : TEXCOORD0; float4 tangent : TANGENT; }; struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; float4 uv : TEXCOORD1; float3 nDirWS : TEXCOORD2; float3 tDirWS : TEXCOORD3; float3 bDirWS : TEXCOORD4; float4 screenPos : TEXCOORD5; }; CBUFFER_START(UnityPerMaterial) half4 _MainTex_ST; half4 _Color; half _ParallaxSize; half _ParallaxLayers; half _MoveSpeed; half _Alpha; half _AlphaExtent; // float _worldDis; float _ruiHua; CBUFFER_END TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_NormalTex); SAMPLER(sampler_NormalTex); TEXTURE2D(_ParallaxTex); SAMPLER(sampler_ParallaxTex); sampler2D _CameraDepthTexture; // TEXTURE2D(_TurbulenceTex); // SAMPLER(sampler_TurbulenceTex); Varyings vert(Attributes v) { Varyings o; o.positionCS = TransformObjectToHClip(v.positionOS.xyz); o.positionWS = TransformObjectToWorld(v.positionOS.xyz); o.nDirWS = TransformObjectToWorldNormal(v.normalOS); o.tDirWS = normalize(TransformObjectToWorld(v.tangent.xyz)); o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w); // o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex) + float2(frac(_Time.y * _MoveSpeed), 0.0); float2 newUV=o.positionWS.xz*0.06; o.uv.xy =TRANSFORM_TEX( newUV, _MainTex) + float2(frac(_Time.y * _MoveSpeed), 0.0); o.uv.zw = o.positionWS.xz * 0.02; o.screenPos = ComputeScreenPos(o.positionCS); return o; } // 从深度值重建世界坐标 float3 ReconstructWorldPosition(float2 uv, float depth) { // 1. 将 UV 转换为 NDC 空间 (Normalized Device Coordinates) float4 ndc = float4(uv * 2.0 - 1.0, depth, 1.0); // 2. 从 NDC 转换到裁剪空间 float4 clipPos = ndc; clipPos.z = depth * 2.0 - 1.0; // 将深度从 [0,1] 转换为 [-1,1] // 3. 应用逆投影矩阵,转换到视图空间 float4 viewPos = mul(unity_CameraInvProjection, clipPos); // 使用 Unity 内置的逆投影矩阵 viewPos /= viewPos.w; // 透视除法 // 4. 应用逆视图矩阵,转换到世界空间 float4 worldPos = mul(UNITY_MATRIX_I_V, viewPos); // 使用 Unity 内置的逆视图矩阵 return worldPos.xyz; } half4 frag(Varyings i) : SV_Target { float2 positionSS = i.positionCS.xy * (_ScreenParams.zw - 1); float depth = tex2D(_CameraDepthTexture, positionSS).r; float3 positionNDC = float3(positionSS * 2 - 1, depth); #if UNITY_UV_STARTS_AT_TOP positionNDC.y = -positionNDC.y; #endif #if REQUIRE_POSITION_VS float4 positionVS = mul(UNITY_MATRIX_I_P, float4(positionNDC, 1)); positionVS /= positionVS.w; float4 positionWS = mul(UNITY_MATRIX_I_V, positionVS); #else float4 positionWS = mul(UNITY_MATRIX_I_VP, float4(positionNDC, 1)); positionWS /= positionWS.w; #endif float dist = length(positionWS - i.positionWS); // return half4(dist * 0.1, 0, 0, 1.0); dist = dist * 0.2; dist = clamp(dist, 0, 1); float ptcpos = length(i.positionWS - _WorldSpaceCameraPos); ptcpos = 1 - (ptcpos - 0) / _ruiHua; ptcpos = clamp(ptcpos, 0, 1); //Light mylight = GetMainLight(); //half3 light = mylight.color; float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS); float3 vDir = normalize(i.positionWS - _WorldSpaceCameraPos.xyz); float3 vDirTS = mul(TBN, vDir); // float2 raoDongUv = SAMPLE_TEXTURE2D(_TurbulenceTex, sampler_TurbulenceTex,i.positionWS.xz * 0.06).r*0.1; // i.uv.xy += raoDongUv; // i.uv.zw += raoDongUv; float3 var_MainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv.zw).rgb; half2 offset = 0.0; half currentDepth = 0.0; half parallaxDepth = 0.0; half preParallaxDepth = 0.0; half heightStep = 1.0 / _ParallaxLayers; half2 offsetTemp = vDirTS.xy / -vDirTS.z * _ParallaxSize; for (int j = 0; j < _ParallaxLayers; j++) { parallaxDepth = 1.0 - SAMPLE_TEXTURE2D_LOD(_MainTex, sampler_MainTex, i.uv.xy + offset, 0).r * var_MainTex.r; if (currentDepth > parallaxDepth) break; preParallaxDepth = parallaxDepth; currentDepth += heightStep; offset = offsetTemp * currentDepth; } half preDepth = currentDepth - heightStep; half A_C = preDepth - preParallaxDepth; half D_B = parallaxDepth - currentDepth; half t = A_C / (D_B + A_C); half height = lerp(preDepth, currentDepth, t); offset += offsetTemp * height; i.uv.xy += offset; half3 finalColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv.xy).rgb * var_MainTex.rgb; float alphaTex = max(var_MainTex.r * finalColor.r, 0.0); half alpha = max(pow(abs(lerp(alphaTex, 1.0, _Alpha)), _AlphaExtent), 0.0) * _Alpha * dist * ptcpos; return half4(finalColor * _Color.rgb, alpha); } ENDHLSL } } }