UnityShader 玻璃效果与程序纹理
玻璃效果
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/Glass"
{
Properties
{
_MainTex("MainTex", 2D) = "white" {}
_TexScale("TexScale", Range(0, 1.0)) = 1
_NormalMap("Normal Map", 2D) = "bump" {}
_Distortion("Distortion", float) = 50
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
GrabPass { "_GrabTex" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _GrabTex;
float4 _GrabTex_TexelSize;
sampler2D _NormalMap;
float _Distortion;
float _TexScale;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 scrPos : TEXCOORD1;
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.scrPos = ComputeGrabScreenPos(o.pos);
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
float3 bump = UnpackNormal(tex2D(_NormalMap, i.uv));
float2 offset = bump.xy * _GrabTex_TexelSize.xy * _Distortion;
fixed4 albedo = tex2D(_GrabTex, (i.scrPos.xy + offset) / i.scrPos.w);
half4 color = tex2D(_MainTex, i.uv);
return albedo * lerp(color, half4(1, 1, 1, 1), _TexScale);
}
ENDCG
}
}
}
分析:玻璃效果是通过对GrabPass采集到的屏幕纹理使用法线纹理进行偏移实现的。首先通过设置SubShader的Tags设置渲染顺序,确保所有不透明物体已经渲染完毕。然后捕捉屏幕图像作为纹理,获取顶点映射到该屏幕的坐标,将该坐标进行缩放和偏移(偏移量依靠法线贴图的xy确定)后获得对应屏幕纹理的颜色。
程序纹理
通过C#脚本生成纹理贴图。即使用脚本对纹理逐像素处理,具体过程可见书本。
同时Unity也支持一种以.sbsar为后缀的材质,可以通过插件SubStance In Unity调整和使用该材质。