在游戏里面经常看到这样的效果,英雄走到障碍物后面,但是我们能够透过障碍物看到英雄的身体,好像我们有了透视眼一般。
都是套路。
其实是程序猿在显示英雄模型的时候,画了两次。
一次是被遮挡的部分用半透明的样子画了一遍。
另一次是没有遮挡的部分画了一遍。
下面在Unity中来实现。
首先新建材质 、Shader、场景。
搭建好场景,一个Cube、一个Capsule
好了,现在是最正常不过的情况了,Capsule被Cube 挡住了。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
下面修改一下 Shader。
Shader "CookBookShaders/Cover Translucent" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque"} LOD 200 ZWrite On ZTest greater //Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off 默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。这里使用 Greater,代表如果当前要渲染的像素 Z值大于 缓冲区中的Z,才渲染,也就是后面的物体覆盖了前面的。 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
只是在 CGPROGRAM 之前加了两句话,设置了两个东西
ZWrite On ZTest greater
ZWrite 代表是否将深度写入深度缓冲中,默认是 On
ZTest 代表通过通过判断深度,来决定当前像素的颜色是否写入颜色缓冲,即是否要用当前像素颜色替换掉之前的像素颜色。
取值有以下几种:
Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off
默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。
这里使用 Greater,代表如果当前要渲染的像素 Z值大于 缓冲区中的Z,才渲染,也就是后面的物体覆盖了前面的。
现在得到如下效果:
这就是第一次的绘制,把后面的Capsule 覆盖掉了前面的Cube。
那下面开始第二次绘制,也就是没有被遮挡的。
既然是没有被遮挡的,那只要按照最普通的方法就可以了,
Shader "CookBookShaders/Cover Translucent" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque"} LOD 200 ZWrite On ZTest greater //Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off 默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。这里使用 Greater,代表如果当前要渲染的像素 Z值大于 缓冲区中的Z,才渲染,也就是后面的物体覆盖了前面的。 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG //上面设置了ZTest greater后,只有被遮挡的地方才渲染出来。所以下面把没有遮挡的地方渲染出来。 ZWrite On ZTest LEqual //Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off 默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。这里使用 Greater,代表如果当前要渲染的像素 Z值大于 缓冲区中的Z,才渲染,也就是后面的物体覆盖了前面的。 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
现在效果是这样的
看起来像是Capsule 在 Cube前面了,Shader实现的效果就是这个,但是我们不能用这个放到游戏中,因为会产生很多误解的。。。
我们来把被遮挡的这一部分,设置为透明,实现类似于LOL 躲草丛的效果。
下面要修改第一次绘制的代码,把它变为透明。
既然要做透明,那么要加上 alpha 的tag才行,然后设置 Alpha。
最终修改如下
Shader "CookBookShaders/Cover Translucent" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque"} LOD 200 ZWrite On ZTest greater //Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off 默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。这里使用 Greater,代表如果当前要渲染的像素 Z值大于 缓冲区中的Z,才渲染,也就是后面的物体覆盖了前面的。 CGPROGRAM #pragma surface surf Lambert alpha //加上alpha让被遮挡的这部分透明显示 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = 0.5f; //设置Alpha为0.5 } ENDCG //上面设置了ZTest greater后,只有被遮挡的地方才渲染出来。所以下面把没有遮挡的地方渲染出来。 ZWrite On ZTest LEqual //Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off 默认是LEqual 如果要绘制的像素的Z值 小余等于深度缓冲区中的值,那么就用新的像素颜色值替换。 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
最终效果转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
示例工程下载:
http://pan.baidu.com/s/1pKT17sf