UnityShader 基础(61)玻璃折射计算
上一节使用CubeMap(环境球贴图)来实现反射效果核心是使用了:
//表面反射方向(视角反方向,物体表面法线)
fixed3 reflectDir = reflect(-viewDir, worldNormal);
//使用反射方向读取环境球图像。
float3 _CubeMapColor = texCUBElod(_CubeMap, fixed4(reflectDir, _CubeMapMipLevel));
如果使用:
//表面折射方向(视角反方向,物体表面法线,折射比率)
fixed3 refractDir = refract(normalize(viewDir), normalize(i.worldNormal),_RefractRatio);
Shader效果
Shader代码
Shader "CRLuo/CRLuo_CubemapNormalTex_Refract"{
Properties{
//反射贴图获取
_CubeMap("环境球贴图",cube) = "Skybox"{}
_CubeMapMipLevel("环境球模糊",range(0,10)) = 0
_RefractRatio("折射率",range(-1,1)) = 1
}
subshader{
Tags{"RenderType" = "Opaque"}
pass {
Tags{"LightMode" = "ForWardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragmentfrag
#include"UnityCG.cginc"
//输入结构
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
//获取表面法线
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
//世界顶点坐标
float3 worldPos:TEXCOORD1;
//世界法线
float3 worldNormal:TEXCOORD2;
};
//获取环境球贴图
samplerCUBE _CubeMap;
float _CubeMapMipLevel;
float _RefractRatio;
//顶点函数
v2f vert(appdata v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f, o);
o.pos = UnityObjectToClipPos(v.vertex);
//物体空间坐标 顶点 转 世界空间坐标
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//物体空间 法线转 世界空间法线
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//摄像机方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
//表面折射率变化
float faceRatio = dot(i.worldNormal, viewDir);
//表面折射发现
fixed3 refractDir = refract(normalize(-viewDir), normalize(i.worldNormal), faceRatio*_RefractRatio);
//获取折射图像
float3 _CubeMapColor = texCUBElod(_CubeMap, float4(refractDir, _CubeMapMipLevel));
//输出仿色贴图
return fixed4(_CubeMapColor,1);
}
ENDCG
}
}
}
不过只有上面的代码是不会有效果的。
需要
1、创建反射探针
2、设置场景静态物体(反射与折射物体)。
3、烘焙环境图
4、把贴图赋予材质球
<hr/>继续吧玻璃做完
Shader代码
Shader &#34;CRLuo/CRLuo_CubemapNormalTex_Glass&#34;{
Properties{
_GlassColor(&#34;玻璃颜色&#34;, Color) = (0.325, 0.807, 0.971, 0.725)
_HighlightColor(&#34;高光颜色&#34;, Color) = (1, 1, 1, 1)
_HighlightPow(&#34;高光范围&#34;,Range(0.001,50)) = 0.1
//反射贴图获取
_CubeMap(&#34;环境球贴图&#34;,cube) = &#34;Skybox&#34;{}
_CubeMapMipLevelA(&#34;环境球反射模糊&#34;,range(0,1)) = 0
_CubeMapMipLevelB(&#34;环境球折射模糊&#34;,range(0,1)) = 0
_RefractRatio(&#34;折射率&#34;,range(-1,1)) = 1
}
subshader{
Tags{&#34;RenderType&#34; = &#34;Opaque&#34;}
//===================创建阴影pass===================
pass
{
//---------------阴影模式
Tags{ &#34;LightMode&#34; = &#34;ShadowCaster&#34; }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//---------------创建阴影
#pragma multi_compile_shadowcaster
#include &#34;UnityCG.cginc&#34;
struct appdata
{
float4 vertex : POSITION;
half3 normal:NORMAL;
};
struct v2f
{
//---------------申请阴影数据结构
V2F_SHADOW_CASTER;
};
v2f vert(appdata v)
{
v2f o;
//---------------放入阴影生成模块
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
//---------------渲染阴影
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
pass {
//---------------向前渲染基础灯光
Tags { &#34;LightMode&#34; = &#34;ForwardBase&#34; }
CGPROGRAM
//---------------向前渲染基础
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragmentfrag
#include&#34;UnityCG.cginc&#34;
//---------------阴影程序集
#include &#34;AutoLight.cginc&#34;
//---------------光照程序集
#include &#34;Lighting.cginc&#34;
//输入结构
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
//世界顶点坐标
float3 worldPos:TEXCOORD1;
//世界法线
float3 worldNormal:TEXCOORD2;
//---------------阴影数据结构
SHADOW_COORDS(3)
};
float4 _GlassColor;
float _HighlightPow;
//获取环境球贴图
samplerCUBE _CubeMap;
float _CubeMapMipLevelA;
float _CubeMapMipLevelB;
float _RefractRatio;
float4 _HighlightColor;
//顶点函数
v2f vert(appdata v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f, o);
o.pos = UnityObjectToClipPos(v.vertex);
//物体空间坐标 顶点 转 世界空间坐标
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//物体空间 法线转 世界空间法线
o.worldNormal = UnityObjectToWorldNormal(v.normal);
//---------------传递且处理阴影数据
TRANSFER_SHADOW(o);
//---------------更改输入顶点变量
UNITY_TRANSFER_FOG(o, o.pos);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//---------------获取阴影
fixed shadow = SHADOW_ATTENUATION(i);
//---------------获取环境色
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
//摄像机方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
//面比率
float faceRatio =abs( dot(i.worldNormal, viewDir));
//世界坐标灯光方向
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//灯光反射
fixed3 reflectLightDir = normalize(reflect(-lightDir, i.worldNormal));
//反射光线与视角点乘,获得高光渐变。
fixed Ramp_Specular = saturate(dot(reflectLightDir, viewDir));
//表面反射方向
fixed3 reflectDir = reflect(normalize(-viewDir), normalize(i.worldNormal));
//获取反射贴图
float3 _reflectColor = texCUBElod(_CubeMap, float4(reflectDir, _CubeMapMipLevelA*8));
//表面折射射方向
fixed3 refractDir = refract(normalize(-viewDir), normalize(i.worldNormal), faceRatio*_RefractRatio);
//获取折射贴图
float3 _refractColor = texCUBElod(_CubeMap, float4(refractDir, (_CubeMapMipLevelB+ _CubeMapMipLevelA)*8));
float3 outColor = lerp(_reflectColor * _HighlightColor.rgb, _refractColor * _GlassColor.rgb * _HighlightColor.rgb, faceRatio)+ pow(Ramp_Specular, _HighlightPow)* _HighlightColor.rgb* shadow;
//输出仿色贴图
return fixed4(outColor+ ambient,1);
}
ENDCG
}
}
}
支持法线贴图
Shader &#34;CRLuo/CRLuo_CubemapNormalTex_Glass&#34;{
Properties{
_GlassColor(&#34;玻璃颜色&#34;, Color) = (0.325, 0.807, 0.971, 0.725)
_BumpMap(&#34;法线贴图&#34;,2D) = &#34;bump&#34;{}
_BumpScale(&#34;法线贴图强度&#34;,Range(-2.0,2.0)) = -1.0
_HighlightColor(&#34;高光颜色&#34;, Color) = (1, 1, 1, 1)
_HighlightPow(&#34;高光范围&#34;,Range(0.001,50)) = 0.1
//反射贴图获取
_CubeMap(&#34;环境球贴图&#34;,cube) = &#34;Skybox&#34;{}
_CubeMapMipLevelA(&#34;环境球反射模糊&#34;,range(0,1)) = 0
_CubeMapMipLevelB(&#34;环境球折射模糊&#34;,range(0,1)) = 0
_RefractRatio(&#34;折射率&#34;,range(-1,1)) = 1
}
subshader{
Tags{&#34;RenderType&#34; = &#34;Opaque&#34;}
//===================创建阴影pass===================
pass
{
//---------------阴影模式
Tags{ &#34;LightMode&#34; = &#34;ShadowCaster&#34; }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//---------------创建阴影
#pragma multi_compile_shadowcaster
#include &#34;UnityCG.cginc&#34;
struct appdata
{
float4 vertex : POSITION;
half3 normal:NORMAL;
};
struct v2f
{
//---------------申请阴影数据结构
V2F_SHADOW_CASTER;
};
v2f vert(appdata v)
{
v2f o;
//---------------放入阴影生成模块
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
//---------------渲染阴影
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
pass {
//---------------向前渲染基础灯光
Tags { &#34;LightMode&#34; = &#34;ForwardBase&#34; }
CGPROGRAM
//---------------向前渲染基础
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragmentfrag
#include&#34;UnityCG.cginc&#34;
//---------------阴影程序集
#include &#34;AutoLight.cginc&#34;
//---------------光照程序集
#include &#34;Lighting.cginc&#34;
//输入结构
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
//获取表面法线
float3 normal:NORMAL;
//获取表面切线
float4 tangent:TANGENT;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
//切线空间转世界空间数据3代4
float4 T2W0:TEXCOORD1;
float4 T2W1:TEXCOORD2;
float4 T2W2:TEXCOORD3;
//---------------阴影数据结构
SHADOW_COORDS(4)
};
float4 _GlassColor;
//定义法线贴图变量
sampler2D _BumpMap;
float4 _BumpMap_ST;
//定义法线强度变量
float _BumpScale;
float _HighlightPow;
//获取环境球贴图
samplerCUBE _CubeMap;
float _CubeMapMipLevelA;
float _CubeMapMipLevelB;
float _RefractRatio;
float4 _HighlightColor;
//顶点函数
v2f vert(appdata v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f, o);
o.uv = TRANSFORM_TEX(v.uv, _BumpMap);
o.pos = UnityObjectToClipPos(v.vertex);
//世界法线
float3 worldNormal = UnityObjectToWorldNormal(v.normal);
//世界切线
float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
//世界副切线
float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
//世界坐标
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//构建变换矩阵
//z轴是法线方向(n),x轴是切线方向(t),y轴可由法线和切线叉积得到,也称为副切线(bitangent, b)
o.T2W0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.T2W1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.T2W2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
//---------------传递且处理阴影数据
TRANSFER_SHADOW(o);
//---------------更改输入顶点变量
UNITY_TRANSFER_FOG(o, o.pos);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//获取法线贴图
float4 Normaltex = tex2D(_BumpMap, i.uv);
//法线贴图0~1转-1~1
float3 tangentNormal = UnpackNormal(Normaltex);
//乘以凹凸系数
tangentNormal.xy *= _BumpScale;
//向量点乘自身算出x2+y2,再求出z的值
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
//向量变换只需要3*3
float3x3 T2WMatrix = float3x3(i.T2W0.xyz,i.T2W1.xyz,i.T2W2.xyz);
//法线从切线空间到世界空间
float3 worldNormal = mul(T2WMatrix,tangentNormal);
//获取顶点世界坐标
float3 WordPos = float3(i.T2W0.w, i.T2W1.w, i.T2W2.w);
//---------------获取阴影
fixed shadow = SHADOW_ATTENUATION(i);
//---------------获取环境色
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
//摄像机方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - WordPos);
//面比率
float faceRatio =abs( dot(worldNormal, viewDir));
//世界坐标灯光方向
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//灯光反射
fixed3 reflectLightDir = normalize(reflect(-lightDir, worldNormal));
//反射光线与视角点乘,获得高光渐变。
fixed Ramp_Specular = saturate(dot(reflectLightDir, viewDir));
//表面反射方向
fixed3 reflectDir = reflect(normalize(-viewDir), normalize(worldNormal));
//获取反射贴图
float3 _reflectColor = texCUBElod(_CubeMap, float4(reflectDir, _CubeMapMipLevelA*8));
//表面折射射方向
fixed3 refractDir = refract(normalize(-viewDir), normalize(worldNormal), faceRatio*_RefractRatio);
//获取折射贴图
float3 _refractColor = texCUBElod(_CubeMap, float4(refractDir, (_CubeMapMipLevelB+ _CubeMapMipLevelA)*8));
float3 outColor = lerp(_reflectColor * _HighlightColor.rgb, _refractColor * _GlassColor.rgb * _HighlightColor.rgb, faceRatio)+ pow(Ramp_Specular, _HighlightPow)* _HighlightColor.rgb* shadow;
//输出仿色贴图
return fixed4(outColor+ ambient,1);
}
ENDCG
}
}
}
页:
[1]