斯涅尔定律-Snell’s Law :n1 * Sin a = n2 * Sin b,n1 和 n2就是两个物体的折射比,a = 入射角 b = 反射角 移动 :n1 / n2 = sin b / sin a = 透射比。
Shader "QShader/Refract"{
Properties{
_BaseColor("Base Color",Color) = (1.0,1.0,1.0,1.0)
_RefractColor("Refract Color",Color) = (1.0,1.0,1.0,1.0)
_RefractAmount("Refract Amount",Range(0,1)) = 1.0
_RefractRatio("Refract Ratio",Range(0.1,1)) = 0.5
_RefractTex("Refract Texture",Cube) = "skybox"{}
}
SubShader{
pass {
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldPos : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldViewDir : TEXCOORD2;
float2 uv : TEXCOORD3;
float3 worldRefractDir : TEXCOORD4;
SHADOW_COORDS(5)
};
fixed4 _BaseColor;
fixed4 _RefractColor;
float _RefractAmount;
float _RefractRatio;
samplerCUBE _RefractTex;
v2f Vertex(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.uv = v.texcoord;
o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);
o.worldRefractDir = refract(normalize(o.worldViewDir),normalize(o.worldNormal),_RefractRatio);
TRANSFER_SHADOW(o)
return o;
}
fixed4 Fragment(v2f i) :SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _BaseColor.xyz;
fixed3 diffuse = _LightColor0.xyz * _BaseColor.xyz * saturate(dot(worldNormal,lightDir));
fixed3 refraction = texCUBE(_RefractTex,i.worldRefractDir) * _RefractColor.xyz;
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4(ambient + lerp(diffuse,refraction,_RefractAmount) * atten,1.0);
}
ENDCG
}
}
}