Unity Shader 中的泳池水面折射实现
水面折射是指光线从一种介质(空气)进入另一种介质(水)时发生弯曲的现象。在计算机图形学中,我们可以使用折射来模拟逼真的水面效果。
为了在 Unity Shader 中实现泳池水面的折射效果,我们需要使用 GrabPass 抓取屏幕空间中的背景图像,然后根据视角方向和水面法线计算折射向量,并使用该向量对背景图像进行采样。
Shader "Unlit/PoolWaterRefraction"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_RefractionStrength ("Refraction Strength", Float) = 0.5
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
GrabPass { }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD1;
float4 worldPos : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _RefractionStrength;
sampler2D _GrabTexture;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.screenPos = ComputeScreenPos(o.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// 计算视角方向
float3 viewDir = normalize(i.worldPos.xyz - _WorldSpaceCameraPos);
// 计算水面法线
float3 normal = float3(0, 1, 0);
// 计算折射向量
float3 refractDir = refract(viewDir, normal, 1.0 / 1.33);
// 计算屏幕空间中的折射偏移
float2 offset = refractDir.xy * _RefractionStrength;
// 对背景图像进行采样
fixed4 col = tex2D(_GrabTexture, i.screenPos.xy / i.screenPos.w + offset);
return col;
}
ENDCG
}
}
}
注意: 以上代码只是一个简单的示例,实际效果可能需要根据具体情况进行调整。
129.81MB
文件大小:
评论区