Unity中溶解shader的总结
转载请标明出处http://www.cnblogs.com/zblade/
在实际的游戏工程中,经常美术和策划会提出溶解的表现要求。比如子弹在飞行的时候,弹道不断的消融;角色受到大型炮弹的攻击,在击飞的时候不断的消融等等诸如此类的表现。一般的消融都是结合粒子系统来实现,通过给粒子Render组件添加material来实现表现。
通过总结我在项目中用到的消融shader,以及在网上查找到的部分消融shader,我做一个基本的shader归类,便于今后的思路查找,其中有任何错误请指出,大家一起学习进步。
实现溶解效果,基本方法是用一个基本纹理贴图+无序图来实现溶解的效果,基本纹理贴图用来表示正常的效果,无序图则表示消融的参考值。通常对消融图是让美术做一张层级图,其中rgba四个通道任意选一个通道作为溶解的无序通道。
下面我先列出参考的一些shader的实现:
1、基本的实现单次溶解的vert/frag shader
Shader "Esfog/Dissolve"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_NoiseTex ("NoiseTex (R)",2D) = "white"{}
_DissolveSpeed ("DissolveSpeed (Second)",Float) =
_EdgeWidth("EdgeWidth",Range(,0.5)) = 0.1
_EdgeColor("EdgeColor",Color) = (,,,)
}
SubShader
{
Tags { "RenderType"="Opaque" } Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc" uniform sampler2D _MainTex;
uniform sampler2D _NoiseTex;
uniform float _DissolveSpeed;
uniform float _EdgeWidth;
uniform float4 _EdgeColor; float4 frag(v2f_img i):COLOR
{
float DissolveFactor = saturate(_Time.y / _DissolveSpeed);
float noiseValue = tex2D(_NoiseTex,i.uv).r;
if(noiseValue <= DissolveFactor)
{
discard;
} float4 texColor = tex2D(_MainTex,i.uv);
float EdgeFactor = saturate((noiseValue - DissolveFactor)/(_EdgeWidth*DissolveFactor));
float4 BlendColor = texColor * _EdgeColor; return lerp(texColor,BlendColor, - EdgeFactor);
} ENDCG
}
} FallBack Off
}
这篇shader来自于Esfog溶解shader,具体的代码解释可以参看原文作者的解释,比较详细,网上很多的相似shader大概都是来自于此。
我只说一下大概的思路,基本就是采样无序图,然后通过其中的某个通道(此处为r)的值,与当前的溶解系数对比,如果当前的通道值小于溶解系数,则说明当前片元需要被剔除。如果不被剔除,则判断当前值距离消融的比例来设置消融的边缘颜色混合。
2、根据外部触发的消融vert/frag shader
上面的shader在开始触发的时候就会不断的消融,在某些时候,我们希望通过外部的时间来控制消融的触发与否,则可以在shader中提供一个外部参数,通过在代码中查找到该material,通过设置material的值来用作触发消融。我们可以在上面的shader的基础上做进一步的改进,改进后的代码如下:
Shader "Esfog/Dissolve"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_NoiseTex ("NoiseTex (R)",2D) = "white"{}
_DissolveSpeed ("DissolveSpeed (Second)",Float) =
_EdgeWidth("EdgeWidth",Range(,0.5)) = 0.1
_EdgeColor("EdgeColor",Color) = (,,,)
_DissolveStartTime("DissolveStartTime",float)=0
}
SubShader
{
Tags { "RenderType"="Opaque" } Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc" uniform sampler2D _MainTex;
uniform sampler2D _NoiseTex;
uniform float _DissolveSpeed;
uniform float _EdgeWidth;
uniform float4 _EdgeColor;
uniform float _DissolveStartTime;
float4 frag(v2f_img i):COLOR
{
bool isNormal = true;
float c = 1;
float4 texColor = tex2D(_MainTex,i.uv);
if(_DissolveStartTime > 0 )
{
float DissolveFactor = saturate((_Time.y-_DissolveStartTime) * _DissolveSpeed);
float noiseValue = tex2D(_NoiseTex,i.uv).r;
if(noiseValue <= DissolveFactor)
{
discard;
}
float EdgeFactor = saturate((noiseValue - DissolveFactor)/(_EdgeWidth*DissolveFactor));
float4 BlendColor = texColor * _EdgeColor;
texColor = lerp(texColor,BlendColor,1 - EdgeFactor);
}
return texColor;
}
ENDCG
}
} FallBack Off
}
通过外部的设置material中的_DissolveStartTime,我们可以控制消融的开始与否,这儿在对消融系数求解的时候,我改为相乘,这样消融的速度就是正确的表明速度。
3、用透明通道来实现的消融
以上两种shader都是基于一张无序图来判定是否消融,如果我们需要做一种透明度逐渐消散的效果,直接采用discard会显得很生硬,不能实现不透明,半透明,透明这样的逐渐消散的效果。如果我们需要用透明的方式来实现消融。这儿我给出一种用透明度实现的消融shader的实现,主要也是通过两张贴图的采用和某些通道值得对比来控制混合的alpha通道。
代码如下:
Shader"Z/DissolveWithBlend"
{
Propertise{
_Color("Color&Alpha",Color)=(,,,)
_MainTex("MainTex",2D)="white"{}
_Mask("Mask",2D)="white"{}
_AlphaFactor("AlphaFactor",Float)=0.0
}
Subshader{
Tags{"Queue"="Transparent" "IgnoreProjector"="True""RenderType"="Transparent"}
Pass{
Tags{"LigthMode"="ForwardBase"}
Blend SrcAlpha OneMinusAlpha
Cull Front
ZWrite off
CGPROGRAM
#include "UnigytCG.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _Mask;
float4 _Mask_ST;
struct a2v{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
}
struct v2f{
float4 pos:SV_POSITION;
float2 uv0:TEXCOORD0;
float2 uv1:TEXCOORD1;
} v2f vert(a2v i){
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,i.vertex);
o.uv0 = TRANSFORM_TEX(i.texcoord,_MainTex);
o.uv1 = TRANSFORM_TEX(i.texcoord,_Mask);
}
fixed4 frag(v2f i):Color{
float4 _mainVar = tex2D(_MainTex,i.uv0);
float4 _maskVar = tex2D(_Mask,i.uv1);
float3 emissive = _Color.rgb * _mainVar.rgb;
return fixed4(emissive,_Color.a * _mainVar.a * step(maskVar.r,_AlphaFactor)); }
ENDCG
}
}
FallBack"Diffuse"
}
基本的操作就是通过设置颜色的alpha通道的透明度,来实现一种用透明度控制的消融效果。当然,这样的shader对于时间的控制,是需要这个特效外部的particle组件来控制的,这里没有设置对时间的操作。
Unity中溶解shader的总结的更多相关文章
- 【unity shaders】:Unity中的Shader及其基本框架
shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...
- 在Unity中使用Shader
1.Material 和 Shader 的关系.一个材质包括一个Shader程序.在Shader中设置的属性能够通过Material可视化设置 2.内建Shader,在5.0之后的版本号中大部分旧的S ...
- Unity中Surface Shader执行过程
- 解读Unity中的CG编写Shader系列七(不透明度与混合)
转自http://www.itnose.net/detail/6098539.html 1.不透明度 当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段 ...
- 解读Unity中的CG编写Shader系列三
转自http://www.itnose.net/detail/6096068.html 在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章 ...
- Unity中的CG编写Shader系列(Blend)
1.不透明度 当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段着色器以及后面的环节的主要工作是输出颜色与深度到帧缓存中,所以两个纹理在每个像素上的颜色 ...
- [转]解读Unity中的CG编写Shader系列6——不透明度与混合
1.不透明度当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段着色器以及后面的环节的主要工作是输出颜色与深度到帧缓存中,所以两个纹理在每个像素上的颜色到 ...
- [转]解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁.后面 ...
- 解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
在上一个样例中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上. 这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁.后 ...
随机推荐
- 马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别
马丁 福勒 Martin Fowler 关于依赖注入和反转控制的区别 http://martinfowler.com/articles/injection.html 中文翻译:http://files ...
- 最近总当机,IT帮网站用了1天时间成功搬家
Posted on 2017年1月22日 最近一两周,IT帮的会员.BA学员和AM学员时不时反馈网站打不开.敏捷个人APP登录不了,有时候又可以但是很慢,还有的时候电信能访问而联通网络访问不了. 这个 ...
- angular表格分页
<!doctype html> <html lang="en" > <head> <meta charset="UTF-8&qu ...
- MEAN教程2-Nodejs安装
安装Node.js稳定版本最简单的办法也是使用二进制文件,Node.js官方网站上提供了下载地址,可用于Linux.Mac OS X和Windows系统.同样要注意下载与目标操作系统架构一致的文件. ...
- Python学习--13 文件I/O
Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系 ...
- Oracle执行计划顺序
先从最开头一直往右看,直到看到最右边的并列的地方,对于不并列的,靠右的先执行:对于并列的,靠上的先执行. 即并列的缩进块,从上往下执行,非并列的缩进块,从下往上执行. 如下示例: Execu ...
- Mac和Linux系统的:Arp欺骗源码
linux系统, 简化版的ARP欺骗工具 精简版, 没有很多代码, 只要把准备好的数据, 发送给到网卡接口, 利用这个工具, 可以让局域网内的一台计算机暂时掉线: #include <stdio ...
- localStorage 如何存储JSON数据并读取JSON数据
localStorage是HTML5提供的再客户端实现本地存储的一种方法,但是localStorage方法只能存储字符串数据,有时候我们需要存储对象到本地比如:JSON:那么,localStorage ...
- vb是如何连接数据库的
vb是如何连接数据库的 刚开始学习数据库时 ,对数据库很不了解,尤其是模块中的代码.照着抄都有很多错的,每一句到底是什么意思呢,根本不懂.于是我就花费了大量的时间去查每一句代码的具体作 ...
- Java模拟新浪微博登陆抓取数据
前言: 兄弟们来了来了,最近有人在问如何模拟新浪微博登陆抓取数据,我听后默默地抽了一口老烟,暗暗的对自己说,老汉是时候该你出场了,所以今天有时间就整理整理,浅谈一二. 首先: 要想登陆新浪微博需要 ...