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

Unity Shader开发:如何基于雨效渲染纹理生成法线贴图

雨效RenderTexture生成法线实现凹凸效果方案

你当前拿到的专用相机输出的雨效RenderTexture属于灰度高度图,亮部对应雨滴的高区域,暗部对应背景低区域,通过邻域像素高度差计算即可生成对应法线,实现凹凸效果,具体实现如下:


1. 核心实现逻辑

  • 利用Unity内置的_MainTex_TexelSize获取纹理单像素尺寸,作为邻域采样的偏移量
  • 采样当前UV上下左右四个相邻位置的灰度值,计算X、Y轴方向的高度差
  • 将高度差转换为切线空间法线,通过_NormalIntensity控制凹凸强度
  • 最终将生成的法线代入光照计算,得到带凹凸感的雨效表现

2. 修改后完整Shader代码

Shader "Unlit/Rain"
{
    Properties
    {
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)
        _NormalIntensity("NormalIntensity",Float) = 0.2
      
    }
        SubShader
        {
            
            Tags { "RenderType" = "Opaque" }
            LOD 100

            Pass
            {
                Tags { "LightMode" = "ForwardBase" }
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"
                #include "Lighting.cginc"
                #include "AutoLight.cginc"

                struct VertexInput {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float3 normal : NORMAL;
                    float4 tangent : TANGENT;

                };

                struct VertexOutput {
                    float2 uv1 : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                    float3 tangentSpaceLight : TEXCOORD1;
                    float3 tangentSpaceView : TEXCOORD2;
                   
                };

                sampler2D _MainTex;
                float4 _MainTex_ST;
                float4 _MainTex_TexelSize;
                half4 _Color;
                float _NormalIntensity;

                VertexOutput vert(VertexInput v) {

                    VertexOutput o;
                    o.uv1 = TRANSFORM_TEX(v.uv, _MainTex);
                    o.vertex = UnityObjectToClipPos(v.vertex);

                    // 计算切线空间的光线和视线方向
                    TANGENT_SPACE_ROTATION;
                    o.tangentSpaceLight = normalize(mul(rotation, ObjSpaceLightDir(v.vertex)));
                    o.tangentSpaceView = normalize(mul(rotation, ObjSpaceViewDir(v.vertex)));

                    return o;
                }

                float4 frag(VertexOutput i) : COLOR{
                    // 采样基础颜色
                    float4 baseCol = tex2D(_MainTex, i.uv1) * _Color;
                    
                    // 邻域采样计算高度差
                    float2 offset = _MainTex_TexelSize.xy * 2;
                    float heightL = tex2D(_MainTex, i.uv1 + float2(-offset.x, 0)).r;
                    float heightR = tex2D(_MainTex, i.uv1 + float2(offset.x, 0)).r;
                    float heightD = tex2D(_MainTex, i.uv1 + float2(0, -offset.y)).r;
                    float heightU = tex2D(_MainTex, i.uv1 + float2(0, offset.y)).r;
                    
                    // 生成切线空间法线
                    float2 delta = float2(heightR - heightL, heightU - heightD) * _NormalIntensity;
                    float3 normal = normalize(float3(delta, 1.0));
                    
                    // 漫反射光照计算
                    float diffuse = max(0, dot(normal, i.tangentSpaceLight));
                    float3 finalCol = baseCol.rgb * _LightColor0.rgb * diffuse;
                    
                    // 可自行添加高光计算增强雨的质感
                    return float4(finalCol, baseCol.a);
                }
                ENDCG
            }
        }
}

3. 调整说明

  • _NormalIntensity默认初始值设为0.2即可,数值越大凹凸感越强,过高会导致法线扭曲失真
  • 如果雨效颗粒偏细,可适当增大采样偏移的倍数(代码里*2的位置),得到更明显的凹凸效果
  • 确保RenderTexture的颜色空间设置为线性,避免gamma矫正导致高度计算偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:45:03