摄像机与主角之间遮挡显示处理(Unity3D开发之二十八)
2018-01-09 18:52
363 查看
今天处理遮挡的时候,本来是想摄像机射线检测,设置建筑半透明效果用来显示被遮挡的角色(有很多游戏也是这样处理的),实现后发现效果实际上不太好。如果被遮挡角色还是敌人或者多个角色时候,不是特别好,比如敌人被遮挡我希望单独区分下。所以改成了现在的直接绘制2D填充色(也就是忽略自身的深度值)来显示。
_NotVisibleColor: 用来绘制挡住时候显示的颜色;
ZTest Greater:表示大于深度缓存中的值的时候(也就是被遮挡的时候),将深度缓存中对应像素的颜色值改为自己的颜色(_NotVisibleColor)
ZWrite Off:表示关闭深度缓存,也就是在上一步写入像素颜色的时候不写入自身深度值(等于遮挡树上绘制颜色,深度值使用树的)
Lighting Off:取消光照,因为我效果希望是2D颜色块的效果。
PlayerDiffuse.shader
什么是深度?
深度其实就是该像素点在3d世界中距离摄像机的距离。离摄像机越远,则深度值(Z值)越大。
什么是深度缓存?
深度缓存中存储着准备要绘制在屏幕上的像素点的深度值。如果启用了深度缓冲区,在绘制每个像素之前,OpenGL会把该像素的深度值和深度缓存的深度值进行比较。如果新像素深度值<深度缓存深度值,则新像素值会取代原先的;反之,新像素值被遮挡,其颜色值和深度将被丢弃。(深度主要起的是比较的作用)
什么是深度测试?
在深度测试中,默认情况是将要绘制的新像素的z值与深度缓冲区中对应位置的z值进行比较,如果比深度缓存中的值小,那么用新像素的颜色值更新深度缓存中对应像素的颜色值。
为什么需要深度?
在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的。而有了深度缓冲以后,绘制物体的顺序就不那么重要了,都能按照远近(Z值)正常显示,这很关键。
那么,在unity中,如果知道了渲染队列,ZWrite,ZTest,如何确定哪个物体先显示呢?
首先,unity先将渲染队列中较前的进行渲染,然后再执行ZWrite,ZTest
ZWrite可以取的值为:On/Off,默认值为On,代表是否要将像素的深度写入深度缓存中(同时还要看ZTest是否通过)。
ZTest可以取的值为:Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off,默认值为LEqual,代表通过比较深度来更改颜色缓存的值。例如当取默认值的情况下,如果将要绘制的新像素的z值小于等于深度缓存中的值,则将用新像素的颜色值更新深度缓存中对应像素的颜色值。
需要注意的是,当ZTest取值为Off时,表示的是关闭深度测试,等价于取值为Always,而不是Never!Always指的是直接将当前像素颜色(不是深度)写进颜色缓冲区中;而Never指的是不要将当前像素颜色写进颜色缓冲区中,相当于消失。
那么,重点来了:
1. 当ZWrite为On时,ZTest通过时,该像素的深度才能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值也会写入颜色缓存。
2. 当ZWrite为On时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。
3. 当ZWrite为Off时,ZTest通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值会写入颜色缓存。
4. 当ZWrite为Off时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。
可以看到,像素的深度能否成功写入深度缓存,条件是ZWrite为On,ZTest通过;
写入深度缓存的作用就是为ZTest的比较做准备。
因为ZWrite默认值为On,ZTest默认值为LEqual,所以这很好地解释了为什么在unity中,距离相机近的东西会阻挡住距离相机远的东西。如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这时我们可以通过修改ZWrite和ZTest来改变物体的遮挡关系!
参考链接:
1. [UnityShader]渲染队列、ZWrite和ZTest
2. 建物に遮蔽されたプレイヤーをシルエット表示する
主要代码
Properties { _NotVisibleColor ("NotVisibleColor (RGB)", Color) = (0.3,0.3,0.3,1) } Pass { ZTest Greater ZWrite Off Lighting Off Color [_NotVisibleColor] }
_NotVisibleColor: 用来绘制挡住时候显示的颜色;
ZTest Greater:表示大于深度缓存中的值的时候(也就是被遮挡的时候),将深度缓存中对应像素的颜色值改为自己的颜色(_NotVisibleColor)
ZWrite Off:表示关闭深度缓存,也就是在上一步写入像素颜色的时候不写入自身深度值(等于遮挡树上绘制颜色,深度值使用树的)
Lighting Off:取消光照,因为我效果希望是2D颜色块的效果。
PlayerDiffuse.shader
Shader "Custom/PlayerDiffuse" { Properties { _NotVisibleColor ("NotVisibleColor (RGB)", Color) = (0.3,0.3,0.3,1) _Color ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Pass { ZTest Greater Lighting Off ZWrite Off Color [_NotVisibleColor] } CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } Fallback "Legacy Shaders/VertexLit" }
渲染深度解释:
参考文章:[UnityShader]渲染队列、ZWrite和ZTest什么是深度?
深度其实就是该像素点在3d世界中距离摄像机的距离。离摄像机越远,则深度值(Z值)越大。
什么是深度缓存?
深度缓存中存储着准备要绘制在屏幕上的像素点的深度值。如果启用了深度缓冲区,在绘制每个像素之前,OpenGL会把该像素的深度值和深度缓存的深度值进行比较。如果新像素深度值<深度缓存深度值,则新像素值会取代原先的;反之,新像素值被遮挡,其颜色值和深度将被丢弃。(深度主要起的是比较的作用)
什么是深度测试?
在深度测试中,默认情况是将要绘制的新像素的z值与深度缓冲区中对应位置的z值进行比较,如果比深度缓存中的值小,那么用新像素的颜色值更新深度缓存中对应像素的颜色值。
为什么需要深度?
在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的。而有了深度缓冲以后,绘制物体的顺序就不那么重要了,都能按照远近(Z值)正常显示,这很关键。
那么,在unity中,如果知道了渲染队列,ZWrite,ZTest,如何确定哪个物体先显示呢?
首先,unity先将渲染队列中较前的进行渲染,然后再执行ZWrite,ZTest
ZWrite可以取的值为:On/Off,默认值为On,代表是否要将像素的深度写入深度缓存中(同时还要看ZTest是否通过)。
ZTest可以取的值为:Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off,默认值为LEqual,代表通过比较深度来更改颜色缓存的值。例如当取默认值的情况下,如果将要绘制的新像素的z值小于等于深度缓存中的值,则将用新像素的颜色值更新深度缓存中对应像素的颜色值。
需要注意的是,当ZTest取值为Off时,表示的是关闭深度测试,等价于取值为Always,而不是Never!Always指的是直接将当前像素颜色(不是深度)写进颜色缓冲区中;而Never指的是不要将当前像素颜色写进颜色缓冲区中,相当于消失。
那么,重点来了:
1. 当ZWrite为On时,ZTest通过时,该像素的深度才能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值也会写入颜色缓存。
2. 当ZWrite为On时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。
3. 当ZWrite为Off时,ZTest通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest通过了,该像素的颜色值会写入颜色缓存。
4. 当ZWrite为Off时,ZTest不通过时,该像素的深度不能成功写入深度缓存,同时因为ZTest不通过,该像素的颜色值不会写入颜色缓存。
可以看到,像素的深度能否成功写入深度缓存,条件是ZWrite为On,ZTest通过;
写入深度缓存的作用就是为ZTest的比较做准备。
因为ZWrite默认值为On,ZTest默认值为LEqual,所以这很好地解释了为什么在unity中,距离相机近的东西会阻挡住距离相机远的东西。如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这时我们可以通过修改ZWrite和ZTest来改变物体的遮挡关系!
参考链接:
1. [UnityShader]渲染队列、ZWrite和ZTest
2. 建物に遮蔽されたプレイヤーをシルエット表示する
相关文章推荐
- (转载)Unity3D研究院之处理摄像机与角色之间被挡时的局部透明效果
- Unity3D研究院之处理摄像机与角色之间被挡时的局部透明效果
- unity3d开发2d游戏中控制摄像机移动以及主角移动
- 在unity3d开发2d游戏控制摄像机移动以及主角移动的方法
- Java开发中的时间对象的显示与处理
- 【Unity开发】Unity3d之MiniJson与LitJson之间的较量
- android 开发listview,gridview,scroolview之间的嵌套,出现子view显示不完整解决方法
- SpringMVC与iReport整合开发时的PDF中文显示处理
- Java开发中的时间对象的显示与处理
- [Unity-14] Unity3d中使用摄像机制作实时显示小地图
- [Unity3D]手机3D游戏开发:如何实现最高分的存储与显示(八)----用TouchScreenKeyboard弹出键盘
- unity3d 摄像机跟随角色时被物体遮挡解决方案
- iOS程序开发引用的第三方库之间出现duplicate symbol时的处理方法
- iOS开发笔记11:表单键盘遮挡、浮点数价格格式化显示、省市区选择器、View Debugging
- iOS程序开发引用的第三方库之间出现duplicate symbol时的处理方法
- unity3d 鼠标和iTween同时处理摄像机时的问题(物品展示)
- Android官方开发文档Training系列课程中文版:高效显示位图之在非UI线程中处理图片
- iOS程序开发引用的第三方库之间出现duplicate symbol时的处理方法
- Android开发,在Activity启动时,默认隐藏软键盘。和遮挡Edittext时的处理
- Android开发中在ListView中经常有Item的点击事件及Button或ImageButton等需要被点击的事件之间的处理方法