3d游戏中人物被遮挡后以其它颜色显示的方法
2016-09-19 11:20
926 查看
好久没有更新博客,最近忙于其他事情了。
今天玩了一下九阴真经,偶然发现里边有一个效果,如图显示:
我们一步步来解释这个效果的原理,涉及的方面其实还挺多的。
首先我们必须清楚地知道,在角色被遮挡的时候,已经暴露出来模型其实是分两次渲染,也就是该模型的着色器必然是存在两个通道的。第一个通道便是遮挡后显示出来的蓝色,第二个通道就是普通情况下显示出来的模型。
第一步:前面的屋子没有能够遮挡住角色的渲染,那么说明角色的渲染一定是在屋子的模型渲染之后进行渲染的并且能通过深度测试,于是第一步里,我们要做的就是将角色模型的渲染队列设置为在屋子的模型队列之后渲染,一般情况下是设置为Tags { "Queue" = "Transparent" },当然你也可以设置其他的,只要保证是在遮挡物之后渲染就可以了。而且明显角色被遮挡并且是在最后渲染,也就是说角色不可能通过深度测试,于是,我们需要加上一条命令ZTest Always,保证一定能覆盖原像素。
第二步:我们知道在没有遮挡的时候显示的模型是正常的,不会显示里面蓝色的部分,所以我们前面说的角色模型的两个着色器通道里面的第二个通道就必须能保证覆盖第一个通道渲染的蓝色像素值,我们可以设置第一个通道的深度值是不写入的,于是就保证了第二个通道的绝对覆盖。所以在第一个通道里面,我们还需要加上ZWrite Off。
第三步:我们理一下第二步,第二步里面说第一个通道的深度值是不写入的,那么在写入之前深度缓冲区中缓存的是哪里的深度值呢?正是屋子模型的深度,也就是说,(1)在被遮挡的时候,当渲染第一个通道的时候,由于ZTest Always和ZWrite Off的存在,使得不需要测试深度,计算机就把像素替换成了模型的像素,但是却保留了屋子模型的深度。当开始渲染第二个通道的时候,却没办法通过深度测试,所以最终输出了第一个通道的颜色;(2)当角色模型没有被遮挡的时候,第一个通道输出后,深度缓冲区缓存的是地面的深度值,而角色模型的深度明显是小于地面的深度值的,所以第二个通道的深度测试通过了,也就覆盖了第一个通道,所以没有遮挡的时候输出了第二个通道的模型颜色。
下面奉上源码:
今天玩了一下九阴真经,偶然发现里边有一个效果,如图显示:
我们一步步来解释这个效果的原理,涉及的方面其实还挺多的。
首先我们必须清楚地知道,在角色被遮挡的时候,已经暴露出来模型其实是分两次渲染,也就是该模型的着色器必然是存在两个通道的。第一个通道便是遮挡后显示出来的蓝色,第二个通道就是普通情况下显示出来的模型。
第一步:前面的屋子没有能够遮挡住角色的渲染,那么说明角色的渲染一定是在屋子的模型渲染之后进行渲染的并且能通过深度测试,于是第一步里,我们要做的就是将角色模型的渲染队列设置为在屋子的模型队列之后渲染,一般情况下是设置为Tags { "Queue" = "Transparent" },当然你也可以设置其他的,只要保证是在遮挡物之后渲染就可以了。而且明显角色被遮挡并且是在最后渲染,也就是说角色不可能通过深度测试,于是,我们需要加上一条命令ZTest Always,保证一定能覆盖原像素。
第二步:我们知道在没有遮挡的时候显示的模型是正常的,不会显示里面蓝色的部分,所以我们前面说的角色模型的两个着色器通道里面的第二个通道就必须能保证覆盖第一个通道渲染的蓝色像素值,我们可以设置第一个通道的深度值是不写入的,于是就保证了第二个通道的绝对覆盖。所以在第一个通道里面,我们还需要加上ZWrite Off。
第三步:我们理一下第二步,第二步里面说第一个通道的深度值是不写入的,那么在写入之前深度缓冲区中缓存的是哪里的深度值呢?正是屋子模型的深度,也就是说,(1)在被遮挡的时候,当渲染第一个通道的时候,由于ZTest Always和ZWrite Off的存在,使得不需要测试深度,计算机就把像素替换成了模型的像素,但是却保留了屋子模型的深度。当开始渲染第二个通道的时候,却没办法通过深度测试,所以最终输出了第一个通道的颜色;(2)当角色模型没有被遮挡的时候,第一个通道输出后,深度缓冲区缓存的是地面的深度值,而角色模型的深度明显是小于地面的深度值的,所以第二个通道的深度测试通过了,也就覆盖了第一个通道,所以没有遮挡的时候输出了第二个通道的模型颜色。
下面奉上源码:
Shader "Outlined/Silhouetted Bumped Diffuse" { Properties { _Color ("Main Color", Color) = (.5,.5,.5,1) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (0.0, 0.03)) = .005 _MainTex ("Base (RGB)", 2D) = "white" { } _BumpMap ("Bumpmap", 2D) = "bump" {} } CGINCLUDE #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; float4 color : COLOR; }; uniform float _Outline; uniform float4 _OutlineColor; v2f vert(appdata v) { // just make a copy of incoming vertex data but scaled according to normal direction v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); float3 norm = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal); float2 offset = TransformViewToProjection(norm.xy); o.pos.xy += offset * o.pos.z * _Outline; o.color = _OutlineColor; return o; } ENDCG SubShader { Tags { "Queue" = "Transparent" } // note that a vertex shader is specified here but its using the one above Pass { Name "OUTLINE" Tags { "LightMode" = "Always" } Cull Off ZWrite Off ZTest Always // you can choose what kind of blending mode you want for the outline Blend SrcAlpha OneMinusSrcAlpha // Normal //Blend One One // Additive //Blend One OneMinusDstColor // Soft Additive //Blend DstColor Zero // Multiplicative //Blend DstColor SrcColor // 2x Multiplicative CGPROGRAM #pragma vertex vert #pragma fragment frag half4 frag(v2f i) : COLOR { return i.color; } ENDCG } CGPROGRAM #pragma surface surf Lambert struct Input { float2 uv_MainTex; float2 uv_BumpMap; }; sampler2D _MainTex; sampler2D _BumpMap; uniform float3 _Color; void surf(Input IN, inout SurfaceOutput o) { o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb * _Color; o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); } ENDCG } Fallback "Outlined/Silhouetted Diffuse" }
相关文章推荐
- DirectX3D游戏制作之---3D场景的渲染及人物动画的显示
- JLabel显示图片,及其它使用方法。。。实现九九乘法表
- javascript实现table选中的行以指定颜色高亮显示的方法
- jQuery实现鼠标滑向当前图片高亮显示并且其它图片变灰的方法
- 一:从实例入手之设置设置颜色交替显示的GridView(方法一)
- 【Unity闲谈】自动处理2.5D(伪3D)游戏中 物体的遮挡关系
- jQuery实现表格颜色交替显示的方法
- OpenGL学习笔记(三)---FreeImage颜色显示错乱的解决方法
- shell脚本中echo显示内容带颜色的实现方法
- IE不能显示网页的背景颜色的解决方法
- 字符串显示不同的颜色的方法
- 火炬之光中人物被遮挡效果在Ogre中的实现方法
- python中pygame针对游戏窗口的显示方法实例分析(附源码)
- [Unity3D]手机3D游戏开发:如何实现最高分的存储与显示(三)----GUI Style与数组的使用
- shell脚本中echo显示内容带颜色的实现方法
- IOS 应用/游戏项目应该如何灵活封装 控件显示样式与项目颜色的公用
- 显示被遮挡的人物或者物体
- VMware WorkStation 5.5 运行 3D 游戏的方法
- Unity 3D:在现有的Android游戏场景中显示AdMob的横幅