Esfog_UnityShader教程_溶解效果Dissolve
溶解效果在游戏中是很常见的,比如在一些神话或者魔法世界中,一些NPC角色在剧情需要时候会身体会渐渐的消失掉.甚至有一些更炫的,比如用火焰喷射器把目标燃尽。这些都可以用到溶解效果。这篇文章主要是讲解一下比较基础的溶解效果如何实现,实现的方法并不唯一,本篇只是其中一种思路。
原理
既然想让角色的身体一块块渐渐消失,不妨就让角色身体上相应的部位不进行渲染(或者改成透明,我们这里选择前者)。那根据什么来判断身体的哪一部分需要被溶解呢,这时候就需要一张额外的贴图或者利用角色纹理贴图的Alpha通道(本篇选择前者)。这个贴图和纹理贴图一样,对应着玩家身体的每一个位置,这样我们就可以根据贴图上某个指定通道的颜色值来控制角色各个身体部位是否溶解了。
另外我们还会涉及到的一个命令叫discard,是由CG提供的,若出现在fragmentShader中表示立即放弃当前处理的片元。也就是说当我们判定当前片远需要溶解的时候我们就使用discard命令。
上面这张图就是用来控制溶解程度的纹理,我们这里比较简单,只使用了R通道,如果你想做的很复杂也可以利用上其它的通道。在本篇中我们将根据时间的推进不断溶解掉贴图上R通道颜色值较小的区域。美术可以利用这张贴图控制角色的任意溶解顺序和效果。由于我的素材都是随便找的,自己又不会画画,所以这个图和角色纹理可能并不搭配,请不要在意。
再看下面这个图,我先来提前说一下本篇Shader在Properties中提供的各个可调节的参数
1.Base(RGB)是角色纹理贴图,不用解释了.
2.NoiseTex(R)是很重重要的,我们用来控制角色溶解的样式贴图,我们只利用了R通道。
3.DissolveSpeed(Second),整个溶解过程需要的时间,单位是秒
4.EdgeWidth,这个就是额外加的一个边缘效果,比如你观察纸在化作灰烬时他的周围会先变成黑褐色。我们这里的EdgeWidth就是定义这个周围区域的大小,注意这个width并不是指的长度,而是定义一个透明度的间隔区间,也就是与基准值相差多少可以算作边缘处理。
5.EdgeColor,和4一样,边缘效果的颜色。
实现
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
}
5~9行,前面解释过了,这里就不再说明了。
18行,这里我使用了unity提供的vert_img顶点着色器,因为我们的需求很简单,只需要进行顶点坐标变换以及把uv传给后面就行了,既然有现成的就不自己写了,它会自动把结果返回到一个v2f_img结构体中.
30行,这里的_Time.y就是从物体一开始渲染到现在所过去的时间unity给我们提供了几个不同的时间参数都保存在_Time中,其中_Time.y是标准的时间,单位(s)。用它去除以_DissolveSpeed.就能得到当前时间已经占用了多少总溶解时间.由于我们要保证比值范围限定在(0,1)的范围内,所以最后调用一个saturate()函数,这个函数式CG提供的就是来完成这个目的的。
31行,从溶解贴图里面取出r通道的值.
32~35行,我们利用刚才算出比值来对溶解贴图里面的R通道颜色值进行判断,如果R通道颜色值小于等于这个比值那么我们就通过discard抛弃当前片远,当前片远的处理会立刻结束。
38行,又是计算一个比值,分子是noiseValue - DissolveFactor,这个值表示溶解贴图上的R通道值和目前的溶解基准值相差多少,而(_EdgeWidth*DissolveFactor)可以这样理解,_EdgeWidth表示可以多大的差值可以算作是边缘,而乘以一个DissolveFactor,就表示边缘最大宽度会随着时间变化时间越长,宽度越宽。最后这两个值相除就代表当前片元的边缘程度,值越大表示离他被溶解掉的时间越长,反之表示他很快就要被溶解掉了.
39行,我们计算一下当前纹理颜色与边缘颜色相乘的值,后面需要用。
41行,这里我们用lerp函数来利用上一步计算出来的(1-EdgeFactor)对原始纹理颜色和上一步中的混合颜色进行一个插值,在解释第38行时候我们已经说了,EdgeFactor越小表示离溶解时间越近,也就是说它边缘化的颜色成分越重,那么由于lerp(x,y,a) = x*(1-a) + y*a;为了让边缘化的颜色重一些我们就使用1-EdgeFactor作为因子了,反之亦然。
好了看一下效果,使用不同的溶解贴图会产生完全不同的效果,下面展示一下我从网上随便找到的两个贴图,由于和原模型纹理并不是一套的,所以看上去会有点怪,不要在意。
使用这个贴图1:
效果如下
使用贴图2:
效果如下:
好了基本效果就是如此,总体来说这个Shader的效果看起来好与不好,主要还是取决于美术提供的溶解贴图是否合适,本节素材并不是一套的,看起来会有点怪。
另外一点就是大家在学习Shader的过程中你总会发现别人打源代码中会出现很多pow,lerp,或者对各个参数的加减乘除,希望大家不要太纠结这些地方的意义,有时候确实是有一定的数学原理,但很多时候都是开发者自己写的一个经验公式,为了调效果而写的。随着你的经验慢慢增多,渐渐的你也会开始使用一些经验公式。效果对了就好,只要不影响性能。毕竟给玩家看的又不是源代码。
尊重他人智慧成果,欢迎转载,请注明作者esfog,原文地址http://www.cnblogs.com/Esfog/p/4469025.html
Esfog_UnityShader教程_溶解效果Dissolve的更多相关文章
- Esfog_UnityShader教程_镜面反射SpecularReflection
系列教程第四篇,本来打算昨天写的,有些小偷懒就今天写了,这一期我们来讨论一下关于镜面反射的基本原理和具体代码.这一篇是承接着上一篇<Esfog_UnityShader教程_漫反射DiffuseR ...
- Esfog_UnityShader教程_前言
很多人在学习Unity的时候对Shader都是一知半解,作为刚入职半年的新人接触Shader的时间也并不长,正因为是新人才能体会到学习Shader时候所遇到的困难和迷茫,无奈于资料不好找,网上难得的几 ...
- Esfog_UnityShader教程_漫反射DiffuseReflection
这篇是系列教程的第三篇,最近工作比较紧,所以这个周六周日就自觉去加了刚回来就打开电脑补上这篇,这个系列的教程我会尽量至少保证一周写一篇的.如果大家看过我的上一篇教程<Esfog_UnitySha ...
- Shader实例:溶解效果(Dissolve)
效果: 图左:一道金光闪过,瞬间灰飞烟灭 图右:燃烧效果,先过渡到黄色,然后渐渐过渡到黑色,最后消失殆尽. 这是游戏中常见的效果,各位可以想想自己玩过的游戏. 手头正在玩的,梦三国手游,死亡的时候就是 ...
- Esfog_UnityShader教程_遮挡描边(原理篇)
咳咳,有段时间没有更新了,最近有点懒!把不少精力都放在C++身上了.闲言少叙,今天要讲的可和之前的几篇有所不同了,这次是一个次综合应用.这篇内容中与之前不同主要体现在下面几点上. 1.之前我们写的都是 ...
- Esfog_UnityShader教程_逐帧动画
有段日子没出这个系列的新文章了,今天就拿一个比较常见也比较基础的利用改变Shader来改变不断调整UV实现播放逐帧动画的小功能.很久没写了就当练练手了.在新版本的Unity中早就已经集成了Sprite ...
- Esfog_UnityShader教程_遮挡描边(实现篇)
在上一篇中,我们基本上说明了遮挡描边实现的一种基本原理.这一篇中我们将了解一下基于这种原理的具体实现代码.本篇中的内容和前几篇教程相比,相对比较难一些,建议先有一些基本的Unity的C#脚本编程经验 ...
- pixijs shader 贴图溶解效果教程
pixijs shader 贴图溶解效果教程 我直接贴代码了 没什么好讲解了 稍微有点基础的人应该能看懂 const app = new PIXI.Application({ transparent: ...
- Spring_MVC_教程_快速入门_深入分析
Spring MVC 教程,快速入门,深入分析 博客分类: SPRING Spring MVC 教程快速入门 资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf Spring ...
随机推荐
- js连接字符串
实例 对象令人感兴趣的一点是用它们解决问题的方式.ECMAScript 中最常见的一个问题是字符串连接的性能.与其他语言类似,ECMAScript 的字符串是不可变的,即它们的值不能改变.请考虑下面的 ...
- getElementById,getElementsByName,getElementsByTagName的区别
1.getElementById 作用:一般页面里ID是唯一的,用于准备定为一个元素 语法: document.getElementById(id) 参数:id :必选项为字符串(String) 返回 ...
- 关于自定义Dialog的一次折腾
<新手,自己的简单理解,勿喷,有更好建议欢迎提出> 1.在设置dialog布局上的时候 我需要做一个圆角的dialog,我像往常一样定义一个<shape>然后做为我的dia ...
- 小制作-css+html旋转木马
源代码: <!DOCTYPE html><html><head> <title></title> <meta charse ...
- HTML 标签 表格
<html> --开始标签 <head> 网页上的控制信息 <title>页面标题</title> </head> <body& ...
- C#的选择语句练习2
1.输入a,b,c三个数,计算一元二次方程ax²+bx+c的根:若a=0,则不是一元二次方程:△=b²-4ac,根的计算公式为-b±√b²-4ac/2a:若△=b²-4ac>0,则方程有两个不一 ...
- imooc-java-作业练习-20150918
小伙伴们,请根据所学知识,编写一个 JAVA 程序,实现输出考试成绩的前三名 要求: 1. 考试成绩已保存在数组 scores 中,数组元素依次为 89 , -23 , 64 , 91 , 119 , ...
- 042. asp.net使用缓存来提高母版页的访问性能
Asp.Net缓存技术是一项非常重要的技术, 当一个页面被频繁的访问, 如果不使用缓存技术, 那么每访问一次就要回发一次服务器, 显然这样对服务器造成很大的负担, 所以, 可以在被频繁访问的页面中设置 ...
- MYCAT 配置(转)
server.xml配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:se ...
- Centos 6.5 rsync+inotify 两台服务器文件实时同步
rsync和inotify是什么我这里就不在介绍了,有专门的文章介绍这两个工具. 1.两台服务器IP地址分别为: 源服务器:192.168.1.2 目标服务器:192.168.1.3 @todo:从源 ...