好久没写博客了,最近在学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,))=3.0//Pow参数
  7. _RimIntensity("Rim Intensity",Range(,))=//边缘光强度
  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=-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. struct a2v{
  75. float4 vertex:POSITION;
  76. float2 texcoord:TEXCOORD0;
  77. };
  78.  
  79. struct v2f{
  80. float4 pos:SV_POSITION;
  81. float2 uv:TEXCOORD0;
  82. };
  83.  
  84. v2f vert(a2v v){
  85. v2f o;
  86. o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
  87. o.uv=v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
  88. return o;
  89. }
  90.  
  91. fixed4 frag(v2f i):SV_TARGET{
  92. fixed3 col=tex2D(_MainTex,i.uv).rgb;
  93.  
  94. return fixed4(col,);
  95. }
  96.  
  97. ENDCG
  98. }
  99.  
  100. }
  101. FallBack "Diffuse"
  102. }

UnityShader之遮挡透明的更多相关文章

  1. Unity遮挡透明渐变

    遮挡透明若没有渐变实现方法: 1.透明中物体存在list中 2.每过一段时间(可以每帧,但是流畅性会降低)摄像机发送一条射线向玩家,out hitInfo 3.list与hitInfo比对,将在lis ...

  2. 主角场景Shader效果:遮挡透明

    基本原理:被遮挡的部分关闭深度写入, 显示透明效果:未被遮挡的部分不关闭深度测试,显示正常贴图效果,即使用两个Pass即可. Pass1:关闭深度写入(ZWrite Off),深度测试渲染较远的物体, ...

  3. UnityShader实现物体被遮挡描边

    之前在网上看到物体遮挡描边的功能,自己也拿来实现了一番.算作第一篇博客的开篇. 先贴出几张效果图,也是个人思路和方案的改进路线吧. ////////////////////////////////// ...

  4. [Canvas]用透明PNG图在背景上画前景能不遮挡背景

    欲看动态效果请点击下载并用Chrome/Firefox浏览器打开index,html. 图例: 从效果可以明显的看到,五角星边缘和中心都没有对背景遮挡. 代码: <!DOCTYPE html&g ...

  5. 使用CSS3的box-shadow实现双透明遮罩层对话框

    box-shadow介绍 在我之前的一篇文章<从天猫和支付宝身上学习opcity与rgba>中,介绍了实现双透明遮罩层效果的两种方法,分别是opacity和rgba.他们需要分别依赖于不同 ...

  6. C# Winform中如何让PictureBox的背景透明

    最近做winform程序,其中有个需求:有两个PictureBox完全重叠,上面一个需要透明,不能遮挡下面的,以为设置上面的BackColor为透明色就可以了,结果不行,上网搜了一下,发现对于我这种需 ...

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

    在实际开发中,遇到在UITextView的frame等于当前控制器的View的frame的情况下,然后运行的时候,发现控制器的Frame的高度y值会从导航条的位置64变化到0. 导致UITextVie ...

  8. Esfog_UnityShader教程_遮挡描边(实现篇)

     在上一篇中,我们基本上说明了遮挡描边实现的一种基本原理.这一篇中我们将了解一下基于这种原理的具体实现代码.本篇中的内容和前几篇教程相比,相对比较难一些,建议先有一些基本的Unity的C#脚本编程经验 ...

  9. Esfog_UnityShader教程_遮挡描边(原理篇)

    咳咳,有段时间没有更新了,最近有点懒!把不少精力都放在C++身上了.闲言少叙,今天要讲的可和之前的几篇有所不同了,这次是一个次综合应用.这篇内容中与之前不同主要体现在下面几点上. 1.之前我们写的都是 ...

随机推荐

  1. springmvc 之 返回值

    springMVC对于controller处理方法返回值的可选类型 spring mvc 支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, Stri ...

  2. [转] (CQRS)命令和查询责任分离架构模式(二) 之 Command的实现

    概述 继续引用上篇文章中的图片(来源于Udi Dahan博客),UI中的写入操作都将被封装为一个命令中,发送给Domain Model来处理. 我们遵循Domain Driven Design的设计思 ...

  3. Web设计思想——渐进增强

    最近在拜读一本Web体验相关的书<渐进增强--跨平台用户体验设计 >,阅读后做些总结,消化一下书中的精髓. 在阅读本文前,可以先思考下面几个问题. 1. 浏览网页的目的是什么? 2. 浏览 ...

  4. Lucence_Curd

    设置Field的类型 new StringField 不分词(id,身份证号,电话...) new StoredField 不分词(链接) new TextField 分词(文本) new Fload ...

  5. React Native 仿天猫物流跟踪时间轴

    最近心血来潮开始学习ReactNative,正好最近有一个项目可能会用到时间轴,页面原型类似于天猫的物流跟踪,如下图 分析之后决定使用ListView来实现,左边的时间轴则使用Art来绘制. 分析左边 ...

  6. Angular中使用Swiper不能滑动的解决方法

    Swiper是目前较为流行的移动端触摸滑动插件,因为其简单好用易上手,很受很多设计师的欢迎. 今天在使用Swiper的时候遇到这个问题: 使用angularjs动态循环生成swiper-slide类, ...

  7. Linux下Shadow socks的安装和配置

    实在受不了在Windows下编程,所以自己就安装了一个Ubutun,公司用的FQ软件shadowsocks在Windows上用起来很简单很爽,但是在Ubutun上的安装和配置就没那么简单了,写下这篇文 ...

  8. 【Android Developers Training】 67. 响应触摸事件

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 安装wamp的方法及过程

    地址栏输入:http://www.xiazaiba.com/html/27954.html下载wamp2.5版本,根据过程安装,其中会安装一些垃圾软件把不该勾选的去掉就可以.点击next,下一步下一步 ...

  10. iOS 实时录音和播放

    需求:最近公司需要做一个楼宇对讲的功能:门口机(连接WIFI)拨号对室内机(对应的WIFI)的设备进行呼叫,室内机收到呼叫之后将对收到的数据进行UDP广播的转发,手机(连接对应的WIFI)收到视频流之 ...