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是为了提高边缘光硬度
代码:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "MyShader/Rim/RimShader" {
Properties{
_RimColor("Rim Color",Color)=(1.0,1.0,1.0,1.0)//边缘光颜色
_RimPower("Rim Power",Range(0.1,))=3.0//Pow参数
_RimIntensity("Rim Intensity",Range(,))=//边缘光强度
_MainTex("Base (RGB)",2D)="white"{}
}
SubShader{
//当所有不透明物体渲染后开始渲染此物体
Tags{"Queue"="Geometry+50" "RenderType"="Opaque"}
Pass{
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
ZWrite Off
ZTest Greater
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _RimColor;
float _RimPower;
float _RimIntensity;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
float4 worldPos:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
v2f vert(a2v v){
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
fixed3 worldNormalDir=normalize(i.worldNormal);
fixed3 worldViewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed rim=-saturate(dot(worldNormalDir,worldViewDir));
fixed3 col=_RimColor.xyz*pow(rim,_RimPower)*_RimIntensity;
return fixed4(col,0.3);
}
ENDCG
}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite On
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct a2v{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(a2v v){
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.uv=v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
return o;
}
fixed4 frag(v2f i):SV_TARGET{
fixed3 col=tex2D(_MainTex,i.uv).rgb;
return fixed4(col,);
}
ENDCG
}
}
FallBack "Diffuse"
}
UnityShader之遮挡透明的更多相关文章
- Unity遮挡透明渐变
遮挡透明若没有渐变实现方法: 1.透明中物体存在list中 2.每过一段时间(可以每帧,但是流畅性会降低)摄像机发送一条射线向玩家,out hitInfo 3.list与hitInfo比对,将在lis ...
- 主角场景Shader效果:遮挡透明
基本原理:被遮挡的部分关闭深度写入, 显示透明效果:未被遮挡的部分不关闭深度测试,显示正常贴图效果,即使用两个Pass即可. Pass1:关闭深度写入(ZWrite Off),深度测试渲染较远的物体, ...
- UnityShader实现物体被遮挡描边
之前在网上看到物体遮挡描边的功能,自己也拿来实现了一番.算作第一篇博客的开篇. 先贴出几张效果图,也是个人思路和方案的改进路线吧. ////////////////////////////////// ...
- [Canvas]用透明PNG图在背景上画前景能不遮挡背景
欲看动态效果请点击下载并用Chrome/Firefox浏览器打开index,html. 图例: 从效果可以明显的看到,五角星边缘和中心都没有对背景遮挡. 代码: <!DOCTYPE html&g ...
- 使用CSS3的box-shadow实现双透明遮罩层对话框
box-shadow介绍 在我之前的一篇文章<从天猫和支付宝身上学习opcity与rgba>中,介绍了实现双透明遮罩层效果的两种方法,分别是opacity和rgba.他们需要分别依赖于不同 ...
- C# Winform中如何让PictureBox的背景透明
最近做winform程序,其中有个需求:有两个PictureBox完全重叠,上面一个需要透明,不能遮挡下面的,以为设置上面的BackColor为透明色就可以了,结果不行,上网搜了一下,发现对于我这种需 ...
- IOS开发之Bug--iOS7View被导航栏遮挡问题的解决
在实际开发中,遇到在UITextView的frame等于当前控制器的View的frame的情况下,然后运行的时候,发现控制器的Frame的高度y值会从导航条的位置64变化到0. 导致UITextVie ...
- Esfog_UnityShader教程_遮挡描边(实现篇)
在上一篇中,我们基本上说明了遮挡描边实现的一种基本原理.这一篇中我们将了解一下基于这种原理的具体实现代码.本篇中的内容和前几篇教程相比,相对比较难一些,建议先有一些基本的Unity的C#脚本编程经验 ...
- Esfog_UnityShader教程_遮挡描边(原理篇)
咳咳,有段时间没有更新了,最近有点懒!把不少精力都放在C++身上了.闲言少叙,今天要讲的可和之前的几篇有所不同了,这次是一个次综合应用.这篇内容中与之前不同主要体现在下面几点上. 1.之前我们写的都是 ...
随机推荐
- Python原理 -- 深浅拷贝
python原理 -- 深浅拷贝 从数据类型说开去 str, num : 一次性创建, 不能被修改, 修改即是再创建. list,tuple,dict,set : 链表,当前元素记录, 下一个元素的位 ...
- Tomcat、JBOSS、WebSphere、WebLogic、Apache等技术概述
Tomcat:应用也算非常广泛的web服务器,支持部分j2ee,免费,出自apache基金组织 JBoss:开源的应用服务器,比较受人喜爱,免费(文档要收费) Weblogic:应该说算是业界 ...
- 关于MATLAB处理大数据坐标文件2017530
今天使用了所有特征并且用SVM测试数据 理由:SVM可以使用特征将测试集划分区域,比较单调.死板 结果:成绩很不理想,无疑又一次说明随机森林更适合大数据处理 第二次提交数据 用MATLAB运行11次运 ...
- JS如何实现真正的对象常量
前言 众所周知ES6新增的const关键字可以用来声明常量,但是它只对基本数据类型生效(Number.String.Boolean等),那如果我们想声明一个常量对象呢?该如何实现,Object内置对象 ...
- 细说Nullable<T>类型
目录一.简介二.语法和用法三.类型的转换和运算四.装箱与拆箱五.GetType()方法六.ToString()方法七.System.Nullable帮助类八.语法糖 一.简介 众所周知,值类型变量不能 ...
- Java 基础 程序流程控制 (上)
Java程序流程控制 (上) Java程序大体分为三种流程控制结构:顺序结构.分支结构.循环结构 顺序结构 程序由上到下的逐行执行,中间没有任何跳转和判断语句. 示例代码如下: public clas ...
- Mysql 根据时间戳按年月日分组统计
Mysql 根据时间戳按年月日分组统计create_time时间格式SELECT DATE_FORMAT(create_time,'%Y%u') weeks,COUNT(id) COUNT FROM ...
- JS之正则表达式
一.正则表达的目标: 1.使用表单事件和脚本函数实现表单验证 2.使用String对象和文本框控件常用属性和方法实现客户端验证 二.什么需要表单验证: 1.表单元素是否为空 2.用户名和密码 3.E- ...
- 在ASP.NET CORE 2.0使用SignalR技术
一.前言 上次讲SignalR还是在<在ASP.NET Core下使用SignalR技术>文章中提到,ASP.NET Core 1.x.x 版本发布中并没有包含SignalR技术和开发计划 ...
- diy toy: image auto-handler
备忘之:) config.xml <?xml version="1.0" encoding="utf-8"?> <config> < ...