You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Unity投影焦散Shader在阴影中不可见并贴近真实光线

解决水下焦散Shader的真实感提升与阴影隐藏问题

嘿,很高兴能帮你优化这个焦散投影Shader!针对你想要的更贴近真实光线和阴影区域不可见这两个需求,我给你整理了具体的修改方案,完全不用你自己从头写Shader,就在你现有代码基础上改就行~


一、先搞定「阴影区域不可见」的核心需求

要让焦散在阴影里消失,我们需要让Shader能读取当前像素的阴影信息,然后根据阴影强度把焦散颜色衰减到0。Unity提供了现成的阴影采样工具,咱们直接加进去:

修改思路:

  • 在顶点着色器里传递阴影坐标
  • 片段着色器中采样阴影贴图,用阴影值控制焦散的可见度

二、提升真实感的几个关键优化

真实的水下焦散有几个特点,咱们针对性调整:

  • 焦散是光线聚焦的加亮效果,不是和底色混合,所以要改混合模式
  • 水下越深,光线被水吸收越多,焦散应该越弱
  • 焦散边缘要柔和过渡,避免硬 cutoff
  • 可以调整默认颜色为更贴近水下的淡蓝色

三、修改后的完整Shader代码

我把所有修改都整合到你的原代码里了,每处修改都加了注释说明:

Shader "Projector/Caustics" {
 Properties {
  _Color ("Caustics Color", Color) = (0.2, 0.8, 1.0, 0) // 改成水下淡蓝色,更真实
  [NoScaleOffset]_MainTex ("Caustics Texture", 2D) = "black" { }
  _Size ("Grid Size", Float) = 10
  _Height ("Water Height", Float) = 2.0
  _DepthBlend ("Depth Attenuation", Float) = 10.0 // 重命名更直观
  _EdgeBlend ("Above Water Fade", Range (0, 100)) = 0.5
  _Multiply ("Intensity", Range (0.5, 3)) = 1.5 // 调整范围更合理
  _LOD ("LOD Bias", Range (1, 1000)) = 100
  _ShadowFade ("Shadow Fade Strength", Range(0, 1)) = 1.0 // 新增:阴影中衰减的强度
 }
 Subshader {
  Tags { "RenderType"="Transparent" "Queue"="Transparent+100" }
  Pass {
   ZWrite Off
   Offset -1, -1
   Blend One One // 改成线性减淡,模拟真实焦散的亮度叠加效果
   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag
   #pragma multi_compile_fog
   #pragma multi_compile_shadowcaster // 新增:启用阴影编译支持
   #include "UnityCG.cginc"
   #include "UnityLightingCommon.cginc" // 新增:引入阴影采样工具

   struct v2f {
    float4 pos : SV_POSITION;
    float2 uv : TEXCOORD0;
    float3 wPos : TEXCOORD1;
    UNITY_FOG_COORDS(2)
    UNITY_SHADOW_COORDS(3) // 新增:存储阴影坐标的变量
   };

   uniform sampler2D _MainTex;
   float4 _MainTex_ST;
   float4 _Color;
   float4x4 unity_Projector;
   float _Size;
   float _Height;
   float _DepthBlend;
   float _EdgeBlend;
   float _Multiply;
   float _LOD;
   float _ShadowFade;

   v2f vert (appdata_tan v) {
    v2f o;
    o.pos = UnityObjectToClipPos (v.vertex);
    o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    o.uv = TRANSFORM_TEX (mul (unity_Projector, v.vertex).xy, _MainTex);
    UNITY_TRANSFER_FOG(o,o.pos);
    UNITY_TRANSFER_SHADOW(o, v.vertex) // 新增:计算并传递阴影坐标
    return o;
   }

   fixed4 frag (v2f i) : COLOR {
    float dist = distance(_WorldSpaceCameraPos, i.wPos);
    // 保持你的平铺纹理采样逻辑
    fixed4 caustic = tex2Dlod (_MainTex, float4(fmod (i.uv, 1 / _Size)*_Size, 0, dist/_LOD)); 

    // 1. 阴影衰减:阴影越浓,焦散越淡
    fixed shadowAtten = UNITY_SHADOW_ATTENUATION(i, i.wPos);
    caustic.rgb *= lerp(1.0, shadowAtten, _ShadowFade);

    // 2. 深度衰减:水下越深,焦散越弱(优化为更平滑的过渡)
    if (i.wPos.y < _Height) {
      float depthFactor = saturate((_Height - i.wPos.y) / _DepthBlend);
      caustic.rgb *= depthFactor;
    } 
    // 3. 水面上方淡入:保留原逻辑,用saturate避免颜色异常
    else {
      float aboveFactor = saturate(1 - (i.wPos.y - _Height)/_EdgeBlend);
      caustic.rgb *= aboveFactor;
    }

    // 4. 应用最终颜色和雾效
    caustic = saturate(caustic);
    UNITY_APPLY_FOG_COLOR(i.fogCoord, caustic, fixed4(0,0,0,0));
    return caustic * _Color * _Multiply ;
   }
   ENDCG
  }
 }
}

四、关键修改点说明

  1. 阴影处理:

    • 加入#pragma multi_compile_shadowcaster宏,让Shader支持阴影采样
    • 通过UNITY_SHADOW_COORDS和UNITY_TRANSFER_SHADOW传递阴影坐标
    • 用UNITY_SHADOW_ATTENUATION获取当前像素的阴影值,新增的_ShadowFade参数可以控制阴影中焦散消失的强度(设为1时完全消失,设为0时不受阴影影响)
  2. 真实感优化:

    • 混合模式改成Blend One One,模拟真实焦散的亮度叠加效果,而非颜色混合
    • 默认颜色调整为淡蓝色,更贴近水下环境
    • 优化深度衰减逻辑,用saturate确保参数值在0-1范围内,避免颜色异常
    • 调整参数范围和命名,更直观好调试

内容的提问来源于stack exchange,提问作者Trafel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:57:43