以下是使用了GrabPass的完整代码
Properties
{
_MainTex("Main Tex",2D)= "white"{}
_BumpMap("Normal Map",2D) ="bump"{}
_CubeMap("Environment CubeMap",Cube) ="_Skybox"{}
_Distortion("Distortion",Range(0,100)) = 10
_RefratAmount("Refract Amount",Range(0.0,1.0)) = 1.0
}
SubShader
{
Tags { "Queue" = "Transparent" "RenderType"="Opaque" }
GrabPass{"_RefractionTex"}
pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
samplerCUBE _CubeMap;
float _Distortion;
float _RefratAmount;
sampler2D _RefractionTex;
float4 _RefractionTex_TexelSize;
struct a2v{
float4 vertex : POSITION;
float3 normal: NORMAL;
float4 tangent : TANGENT;
float2 texcoord : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
float4 scrPos : TEXCOORD0;
float4 uv : TEXCOORD1;
float4 TtoW0 : TEXCOORD2;
float4 TtoW1 : TEXCOORD3;
float4 TtoW2 : TEXCOORD4;
};
v2f vert (a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.scrPos = ComputeGrabScreenPos(o.pos);
o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap);
float3 worldPos = mul(unity_ObjectToWorld,v.vertex);
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal,worldTangent) * v.tangent.w;
o.TtoW0 = float4(worldTangent.x,worldBinormal.x,worldNormal.x,worldPos.x);
o.TtoW1 = float4(worldTangent.y,worldBinormal.y,worldNormal.y,worldPos.y);
o.TtoW2 = float4(worldTangent.z,worldBinormal.z,worldNormal.z,worldPos.z);
return o;
}
fixed4 frag (v2f i) : SV_Target{
float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 bump = UnpackNormal(tex2D(_BumpMap,i.uv.zw));
float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
i.scrPos.xy = offset + i.scrPos.xy;
fixed3 refrCol = tex2D(_RefractionTex,i.scrPos.xy/i.scrPos.w).rgb;
bump = normalize(half3(dot(i.TtoW0.xyz,bump),dot(i.TtoW1.xyz,bump),dot(i.TtoW2.xyz,bump)));
fixed3 reflDir = reflect(-worldViewDir,bump);
fixed4 texColor = tex2D(_MainTex,i.uv.xy);
fixed3 reflCol = texCUBE(_CubeMap, reflDir).rgb * texColor.rgb;
fixed3 finelColor = reflCol * (1-_RefratAmount) + refrCol * _RefratAmount;
return fixed4(finelColor,1);
}
ENDCG
}
}
FallBack "Diffuse"
在本代码中,通过使用“ GrabPass{"\_RefractionTex"}”这一行代码,来定义了一个名为\_RefractionTex的纹理中。
再通过 “sampler2D \_RefractionTex;”来创建一个同名纹理采样变量来供后面的pass进行访问。
通常用来实现玻璃等透明材质的模拟,例如:使用法线来模拟折射,而不是简单的原屏幕颜色进行混合。
在使用中需要小心物体的渲染队列设置,“Tags { "Queue" = "Transparent" "RenderType"="Opaque" }”需要把渲染队列设置成Transparent,这样才能保证所有不透明物体都已经被绘制在屏幕上。
在本文示例中:
使用了“\_BumpMap("Normal Map",2D) ="bump"{}”获取法线贴图来修改模型的法线信息。
使用了通过设置"GrabPass"得到的抓取透明物体背后采样信息,得到折射信息相关代码:“fixed3 refrCol = tex2D(\_RefractionTex,i.scrPos.xy/i.scrPos.w).rgb;” 为此须先使用“UnityCG.cginc“中声明的“ComputeGrabScreenPos()”函数来得到被抓取的屏幕图像采样坐标。“o.scrPos = ComputeGrabScreenPos(o.pos);”
在模拟折射时,使用了切线空间下的法线对屏幕纹理坐标的偏移后再采样。
使用了一个CubeMap来模拟玻璃的反射,相关代码:“fixed3 reflCol = texCUBE(\_CubeMap, reflDir).rgb \* texColor.rgb;”
这篇博客介绍了如何在Unity 3D中使用GrabPass技术来实现复杂的视觉效果,包括法线贴图模拟折射和立方体贴图模拟反射。代码示例展示了如何结合纹理采样、屏幕坐标偏移以及切线空间法线来创建透明物体的折射效果,并利用反射向量从CubeMap中获取反射颜色,最终合成折射和反射的最终颜色。此外,还提到了渲染队列的设置和透明物体的处理方式。
1750

被折叠的 条评论
为什么被折叠?



