UnityShader之遮挡透明

  好久没写博客了,最近在学shader,不得不说,shader真的非常美妙,我沉迷其中无法自拔= =

  之前做过一个遮挡透明的功能,当物体遮挡住主角时,该物体会变成半透明显示出主角。这次同样是遮挡透明的功能,不过,变透明的刚刚相反,是主角变成半透明,更严谨的说是主角被遮挡的那一部分变成半透明。

  先放出结果图:

  当被遮挡时,遮挡部分透明处理,那么需要涉及渲染深度的知识。引擎是如何判断哪个物体在前面哪个物体在后面呢?

  深度:每个像素有自己的深度值,离摄像机近的深度小,远的深度大

  深度缓冲区:存储每个像素的深度

  颜色缓冲区:存储每个像素的颜色

  过程:首先比较像素的深度与深度缓冲区同一位置的深度,如果前者小于后者,则未通过深度测试;否则,通过深度测试,将前者写入后者,将该像素的颜色写入到颜色缓冲区。将颜色缓冲区像素颜色显示到屏幕上。

  通过这个过程即可把深度小的像素剔除掉,将深度大的显示到屏幕上,从而实现物体的前后顺序。

  UnityShader提供了ZWrite 和 ZTest对应深度写入和深度测试。

  调整ZWrite可以控制是否将深度写入到深度缓冲区,当然,前提是深度测试通过,如果没通过测试,那么肯定是无法写入的

  调整ZTest可以定义上述中前者与后者的比较关系,默认为LEqual即小于等于时通过测试

  那么可以得到一种实现思路,用两个PASS:

  第一个PASS:ZTest 为 Greater,ZWrite 为 Off,当该像素被遮挡即深度大于深度缓冲区对应位置深度时执行该PASS,那么就可以在该PASS中实现被遮挡像素的效果。

  第二个PASS:ZTest为LEqual,ZWrite 为 On,这个PASS与上述PASS是互斥的,在这个PASS中实现未被遮挡像素的效果。

  设置ZWrite 是为了防止两个PASS都执行,如果第一个PASS的ZWrite为On,某一像素未被遮挡时,执行第一个PASS,将像素深度写入深度缓冲区,然后轮到第二个PASS进行深度测试时也会通过,因为小于等于嘛。

  

  被遮挡像素透明实现用了边缘光使得更炫酷。边缘光公式大概如下:

  fixed   rim=1-saturate(dot(worldNormalDir,worldViewDir));

  fixed3 finalCol=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity

  通过第一个式子可以得到一个参数rim,顶点法线方向与视角方向契合度越高则rim越小,否则rim越大,即越靠近边缘rim越大

  第二个式子中pow是为了提高边缘光硬度

  代码:

  1 // Upgrade NOTE: replaced ‘_Object2World‘ with ‘unity_ObjectToWorld‘
  2
  3 Shader "MyShader/Rim/RimShader" {
  4     Properties{
  5         _RimColor("Rim Color",Color)=(1.0,1.0,1.0,1.0)//边缘光颜色
  6         _RimPower("Rim Power",Range(0.1,10))=3.0//Pow参数
  7         _RimIntensity("Rim Intensity",Range(0,100))=10//边缘光强度
  8
  9         _MainTex("Base (RGB)",2D)="white"{}
 10     }
 11     SubShader{
 12         //当所有不透明物体渲染后开始渲染此物体
 13         Tags{"Queue"="Geometry+50" "RenderType"="Opaque"}
 14
 15         Pass{
 16             Blend SrcAlpha OneMinusSrcAlpha
 17             Cull Off
 18             ZWrite Off
 19             ZTest Greater
 20
 21             CGPROGRAM
 22             #pragma vertex vert
 23             #pragma fragment frag
 24             #include "UnityCG.cginc"
 25
 26                 fixed4 _RimColor;
 27                 float _RimPower;
 28                 float _RimIntensity;
 29
 30                 struct a2v{
 31                     float4 vertex:POSITION;
 32                     float3 normal:NORMAL;
 33                 };
 34
 35                 struct v2f{
 36                     float4 pos:SV_POSITION;
 37                     float4 worldPos:TEXCOORD0;
 38                     float3 worldNormal:TEXCOORD1;
 39                 };
 40
 41                 v2f vert(a2v v){
 42                     v2f o;
 43                     o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
 44                     o.worldPos=mul(unity_ObjectToWorld,v.vertex);
 45                     o.worldNormal=UnityObjectToWorldNormal(v.normal);
 46                     return o;
 47                 }
 48
 49                 fixed4 frag(v2f i):SV_TARGET{
 50                     fixed3 worldNormalDir=normalize(i.worldNormal);
 51                     fixed3 worldViewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
 52                     fixed rim=1-saturate(dot(worldNormalDir,worldViewDir));
 53
 54                     fixed3 col=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity;
 55                     return fixed4(col,0.3);
 56                 }
 57             ENDCG
 58         }
 59
 60         Pass{
 61             Tags{"LightMode"="ForwardBase"}
 62             ZWrite On
 63             ZTest LEqual
 64             CGPROGRAM
 65             #pragma vertex vert
 66             #pragma fragment frag
 67             #include "UnityCG.cginc"
 68             #include "Lighting.cginc"
 69             #include "AutoLight.cginc"
 70
 71                 sampler2D _MainTex;
 72                 float4 _MainTex_ST;
 73
 74
 75                 struct a2v{
 76                     float4 vertex:POSITION;
 77                     float2 texcoord:TEXCOORD0;
 78                 };
 79
 80                 struct v2f{
 81                     float4 pos:SV_POSITION;
 82                     float2 uv:TEXCOORD0;
 83                 };
 84
 85                 v2f vert(a2v v){
 86                     v2f o;
 87                     o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
 88                     o.uv=v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
 89                     return o;
 90                 }
 91
 92                 fixed4 frag(v2f i):SV_TARGET{
 93                     fixed3 col=tex2D(_MainTex,i.uv).rgb;
 94
 95                     return fixed4(col,1);
 96                 }
 97
 98             ENDCG
 99         }
100
101
102     }
103     FallBack "Diffuse"
104 }

时间: 2024-07-31 14:35:11

UnityShader之遮挡透明的相关文章

Unity遮挡透明渐变

遮挡透明若没有渐变实现方法: 1.透明中物体存在list中 2.每过一段时间(可以每帧,但是流畅性会降低)摄像机发送一条射线向玩家,out hitInfo 3.list与hitInfo比对,将在list中但是没有在hitInfo中的物体转变成不透明,list.remove:将在hitInfo中但是没有在list中转变成透明,list.add 若有渐变,实现比较麻烦一点,物体有两个状态:转变成透明过程中.转变成不透明过程中,添加两个list(InTransparent,outTransparent

IOS开发之Bug--iOS7View被导航栏遮挡问题的解决

在实际开发中,遇到在UITextView的frame等于当前控制器的View的frame的情况下,然后运行的时候,发现控制器的Frame的高度y值会从导航条的位置64变化到0. 导致UITextView的frame也跟着一起移动. 这个问题本质其实就是iOS7View被导航栏遮挡问题,于是经过百度搜索到答案.特此下面 复制拷贝 做个简单的笔记: self.navigationController.navigationBar.translucent = NO; 如果在iPad上用了split vi

[UnityShader]点染队列、ZWrite和ZTest

转载自:http://www.myexception.cn/mobile/1902628.html [UnityShader]渲染队列.ZWrite和ZTest 参考链接:http://blog.csdn.net/zhuyingqingfen/article/details/18979547 http://blog.csdn.net/lysc_forever/article/details/13614449 (1)什么是深度? 深度其实就是该像素点在3d世界中距离摄象机的距离,深度值(Z值)越大

网页设计中透明效果的使用技巧

在网页设计中使用透明效果是件既美观又冒险的事儿.透明效果的使用是把色块,文本或图像“变薄”或者降低饱和度,使颜色变浅透明,这样下个图层的内 容就能穿透显示出来.这种方法如果用好了,效果将会特别棒——能突出显示文本或者在图像的特定区域形成焦点.但设计者在运用透明效果时要特别小心,因为这 么做可能会影响页面的可读性.要是框和文本的透明度不对,更可能会影响到整体的设计. 下文是一些注意事项以及巧妙运用透明效果的成功案例. 用“透明效果”来制造对比 使 用透明效果最大的优点是可以形成对比.设计者可以在图

解决SurfaceView调用setZOrderOnTop(true)遮挡其他控件的问题

SurfaceView遮挡其他控件的项目背景: 最近在做播放器项目,由于底层实现是用Surface和OpenGL切换渲染,所以在布局里面同时使用了GLSurfaceView和SurfaceView,同时播放控制按钮是自定义的,也没有使用Android自己提供的MediaCtroller控件.在这种背景下,问题出现了,如果有相关开发基础的同学应该知道,当SurfaceView和GLSurfaceView同时在一个布局里面,如果想让SurfaveView显示图片或者视频必须要调用SurfaceVie

2016.5.30实现透明Panel及控件置顶的方法

想放置一个透明Panel在某控件上端,实现效果是可透过此Panel看见下面控件,但鼠标点击却无任何反应. 1.新建置自定义Panel类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; namespace NavDataManager { public class MyTran

图记 2016.1.5 透明状态栏

现在时间是2016年1月5号凌晨1:11,呃,光棍时间~ 今天主要磨蹭了一下透明石状态栏,虽然效果实现了,但还是不完美,如图 虽然实现了状态栏的 透明,但是RaidoButton下面那一大段空白看着特别的别扭,群里问了一溜遍,也没有答案...只好想别的办法来弥补了,我想着下面加一个状态栏,类似于这样 也许会显得好一些 于是重新写布局,在写布局的时候,顺手运行了一下,发现竟然特么的成了 原来实现透明状态栏的代码是从网上找来的,结果其中有一条属性并不适用我这个场景,唉...理解不透彻.... 透明状

UnityShader入门精要-3.3 UnityShader的结构

一个UnityShader的基础结构如下所示: Shader "ShaderName"{ Properties{ //属性 } SubShader{ //显卡A使用的子着色器 } SubShader{ //显卡B使用的子着色器 } Fallback "VertexLit" } Unity在背后根据使用的平台来吧这些结构编译成真正的代码和Shader文件,开发者只需要和UnityShader打交道即可.(Unity编写Shader的语言是ShaderLab) 属性:在

Unity Shaders and Effects Cookbook (D-1) 设置 ZTest 来实现遮挡半透效果

在游戏里面经常看到这样的效果,英雄走到障碍物后面,但是我们能够透过障碍物看到英雄的身体,好像我们有了透视眼一般. 都是套路. 其实是程序猿在显示英雄模型的时候,画了两次. 一次是被遮挡的部分用半透明的样子画了一遍. 另一次是没有遮挡的部分画了一遍. 下面在Unity中来实现. 首先新建材质 .Shader.场景. 搭建好场景,一个Cube.一个Capsule 好了,现在是最正常不过的情况了,Capsule被Cube 挡住了. 转自http://blog.csdn.net/huutu http:/