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
相关产品推荐
相关产品推荐

