参考《shader入门精要》
效果
思路
1、先生成立方体纹理的对象
2、在shader中计算出折射方向
3、根据折射方向对立方体纹理采样
实现
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/Refract" {
Properties {
_Color("Color", Color) = (1,1,1,1)
_RefractColor ("RefractorColor", Color) = (1,1,1,1)
_RefractAmount ("RefractAmount", Range(0,1)) = 1.0//折射程度
_RefractRatio("Ratio", Range(0.1,1)) = 0.5//入折介质与折射介质的比值
_Cubemap("CubeMap",Cube) = "_Skybox" {} //立方体纹理
}
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"} // 渲染类型::不透明物体 渲染队列:不透明几何体
Pass {
Tags { "LightMode"="ForwardBase" } //前向渲染
CGPROGRAM
编译PassType.ForwardBase所需的所有变体
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Color;
samplerCUBE _Cubemap; //定义立方体纹理的数据类型
float _RefractRatio;
fixed4 _RefractColor;//折射颜色
fixed _RefractAmount;//折射程度
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldPos : TEXCOORD0;
fixed3 worldNormal : TEXCOORD1;
fixed3 worldViewDir : TEXCOORD2;
fixed3 worldRefl : TEXCOORD3;
SHADOW_COORDS(4)//声明了一个名为_ShadowCoord的阴影纹理坐标变量。
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;
o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);
o.worldRefl = refract( -normalize(o.worldViewDir), normalize(o.worldNormal ), _RefractRatio );
//refract函数计算折射的出射光线的方向,
//第一个参数是入射方向,必须归一化
//第二个参数是表面法线,需归一化
//第三个参数是入射光线所在介质的折射率和折射光线所在介质的折射率的比值
//返回的是折射光线的方向
TRANSFER_SHADOW(o);
//SHADOW_COORDS这个宏后面的参数是指第几个通道,不要和其他的出现冲突,也就是要改变投影的颜色话必须要占用一个通道。
//在顶点处理器里调用TRANSFER_SHADOW。
//然后像素着色器调用UNITY_LIGHT_ATTENUATION,返回的就是这个像素是否存在阴影中。
//此时得到的atten就是综合了衰减和阴影的结果,可以用其来作为【衰减】和【阴影】的因子与最终的光照颜色相乘。
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLight = normalize( UnityWorldSpaceLightDir(i.worldPos));
fixed3 worldViewDir = normalize(i.worldViewDir);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 diffuse = _LightColor0.rgb * _Color.rgb * saturate( dot( worldNormal,worldLight ));
fixed3 refraction = texCUBE( _Cubemap, i.worldRefl ).rgb * _RefractColor.rgb; //对立方体纹理采样(提供折射的方向),
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
fixed3 color = (ambient + lerp( diffuse,refraction, _RefractAmount ) * atten); //lerp(a,b,w) 根据w返回a到b之间的插值 根据折射程度变量,返回插值。
return fixed4(color,1.0);
}
ENDCG
}
}
FallBack "Reflective/VertexLit"
}