Unity光晕剑效果的Shader简单实现
最近遇到了一个需求,想要一种在刀剑上带有光晕的酷炫效果,甚至是还想要有闪烁呼吸效果,于是就写了一个简单的叫LightSwrod的Shader去实现,先上图看看效果吧。
简单展示
这是剑本身的样子
这是用了LightSword后的效果
(原谅我的审美吧~~~调了半天也就这难看的样子T_T)
这是Inspector里面Material的参数
参数的解释将在后面进行细致讲解
创建流程
来讲述一下创建光剑效果的流程吧
1.准备两张贴图:
一张是剑体本身的贴图,是真正要显示出来的剑体
一张是要展现光晕效果,给Shader用的Alpha贴图
Alpha贴图可以拿剑体本身的贴图复制一份来修改,由于Shader只取Alpha贴图的Alpha值,所以修改方式是在剑体周围加上渐变透明的颜色,最终光晕颜色越浅的地方Alpha值越低。
2.创建Sprite:
先将贴图转换成sprite格式
将图片子节点下的sprite拖到Hierarchy下变成一个GameObject
再将贴图调到Advanced格式
注意:需要将Mesh Type调成FullRect模式,使Sprite生成的Mesh是一个完整的矩形,
否则Unity会自动 生成一个被裁减的Mesh,在这部分之外是不会被渲染的,导致光晕有被裁剪的感觉,如下图
3.创建Material和Shader:
Material可以直接在Project里面右键->Create->Material来创建,Shader同理 。
如下,我们创建了Material和Shader
接着将Shader拖到Material上,但你你看到的Inspector的样子一定跟上面给不一样,因为Shader还没有改写好,下面就开始讲述如何编写这个Shader。
4.Shader编写:
先把完整的Shader贴出来吧:
// 发光剑的光晕实现
// By XiaoZeFeng
Shader "custom/LightSword"
{
Properties
{
_MainTex("Main Texture (RGB)", 2D) = "white" {} // 主贴图 //
_MainColorTimes("MainColorTimes", Range(0, 30)) = 1 // 主图颜色增强倍数 //
_EmissionTex("_EmissionTex", 2D) = "white" {} // 光晕Alpha图,取Alpha值填补Emission颜色 //
_EmissionAlphaTimes("EmissionAlphaTimes", Range(0, 50)) = 1 // 光晕Alpha增强倍数 //
_EmissionAlphaExponent("EmissionAlphaExponent", Range(0, 10)) = 1 // 光晕Alpha指数,用于消除黑边 //
_Emission1("Emmisive Color1", Color) = (0,0,0,0) // 剑体本身的发光颜色 //
_EmissionColorTimes1("EmissionColorTimes1", float) = 1 // 剑体本身的发光颜色倍数 //
_Emission2("Emmisive Color2", Color) = (0,0,0,0) // 剑体光晕的发光颜色 //
_EmissionColorTimes2("EmissionColorTimes2", float) = 1 // 剑体光晕的发光颜色倍数 //
_AllAlpha("AllAlpha", Range(0, 1)) = 1 // 整体Alpha值 //
}
SubShader
{
Tags
{
"Queue" = "Transparent+100"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
LOD 100
Cull Off
ZWrite Off
AlphaTest Off
Blend SrcAlpha OneMinusSrcAlpha
Fog{ Mode Off }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
uniform fixed _MainColorTimes;
sampler2D _EmissionTex;
uniform float _EmissionAlphaTimes;
uniform float _EmissionAlphaExponent;
uniform fixed4 _Emission1;
uniform fixed _EmissionColorTimes1;
uniform fixed4 _Emission2;
uniform fixed _EmissionColorTimes2;
uniform fixed _AllAlpha;
struct appdata_t
{
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD;
};
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
return OUT;
}
fixed4 frag(v2f IN) : COLOR
{
fixed4 mainColor = tex2D(_MainTex, IN.texcoord);
fixed4 emisionColor = tex2D(_EmissionTex, IN.texcoord);
mainColor.rgb = mainColor.rgb * _MainColorTimes
+ _Emission1 * mainColor.a * _EmissionColorTimes1
+ _Emission2 * (1 - mainColor.a) * emisionColor.a * _EmissionColorTimes2;
mainColor.a = max(mainColor.a, pow(emisionColor.a, _EmissionAlphaExponent)
* _EmissionAlphaTimes) * _AllAlpha;
return mainColor;
}
ENDCG
}
}
}
Shader讲解
properties
在properties里面定义了10个参数,其中两个是贴图,两个是颜色,其他都是float数值,其他参数所表达的含义都在注释中有标注。
vertex
vertex方法里正常的将物体投影到屏幕上,惯例的做法,没有什么特殊性,就不过多的解释了。
fragment
fragment方法是实现剑光晕效果的主体,将由两个公式来分别计算光晕剑每个像素点的颜色和Alpha值。
首先是取出剑本体和Alpha贴图上关于当前像素点的颜色和Alpha值
fixed4 mainColor = tex2D(_MainTex, IN.texcoord);
fixed4 emisionColor = tex2D(_EmissionTex, IN.texcoord);
接着是像素点的颜色
mainColor.rgb = mainColor.rgb * _MainColorTimes
+ _Emission1 * mainColor.a * _EmissionColorTimes1
+ _Emission2 * (1 - mainColor.a) * emisionColor.a * _EmissionColorTimes2;
像素点的颜色由三方面组成:
1.剑主体贴图的颜色。
2.剑体自发光的颜色。
3.剑体周围光晕的颜色。
1.剑主体贴图的颜色。
mainColor.rgb * _MainColorTimes
这里将剑体本身的颜色乘以_MainColorTimes参数来把剑体本身颜色增强,以免在光晕中显得单薄。
2.剑体自发光的颜色。
_Emission1 * mainColor.a * _EmissionColorTimes1
_Emission1是剑体发光颜色参数,乘以mainColor.a主贴图的Alpha值使其剑本体上有颜色变化,在剑体以外,也就是Alpha值为0的地方无效;最后乘以_EmissionColorTimes1颜色增强参数同样用于将发光色增强。
3.剑体周围光晕的颜色。
_Emission2 * (1 - mainColor.a) * emissionColor.a * _EmissionColorTimes2
_Emission2是剑体周围发光颜色参数,乘以(1 - mainColor.a) 使其剑本体以外有颜色变化,在剑体本身,也就是Alpha值大于0的地方影响减弱或不影响;接着乘以emissionColor.a 也就是Alpha贴图的Alpha值使光晕效果根据Alpha贴图的Alpha值渐变显示出向周围渐渐变淡的效果,最后乘以_EmissionColorTimes2颜色增强参数同样用于将发光色增强。
通过这三种颜色的叠加,实现了剑体颜色,剑体自发光和周围光晕的效果。
最后是像素点颜色透明度Alpha值的计算:
mainColor.a = max(mainColor.a, pow(emisionColor.a, _EmissionAlphaExponent) * _EmissionAlphaTimes) * _AllAlpha;
输出颜色的透明度等于剑主体的透明度和周围光晕的透明度间的最大值最后乘以_AllAlpha参数,取最大值的原因在于使剑体和光晕得以显示,因为在第一张贴图中,除剑体以外部分的Alpha值都是0,所以需要将周围光晕本身的Alpha值也给计算进去。
CGpow(emisionClolor.a, _EmissionAlphaExponent) * _EmissionAlphaTimes
是计算剑体周围光晕Alpha值的公式,也许你有疑问,这里直接取第二章贴图的Alpha值不就好了,为啥要搞这么复杂的计算?
首先pow()是一个指数运算方法,他将Alpha贴图的Alpha值进行了指数运算,使得其渐变率变得更加明显,这么做的原因是在Shader的实现过程中发现在Alpha贴图外侧,也就是Alpha值变低时会有黑边的效果,样子如下
通过这个指数运算,可以明显的减缓这种问题,接着乘以_EmissionAlphaTimes参数同样是为了增强Alpha值的效果,以达到让光晕更加明显的效果但同时也会增强黑边的问题,所以这个值需要跟_EmissionAlphaExponent参数进行配合使用。
在Alpha值计算的最后,还将总的Alpha值乘以_AllAlpha参数,这是为了实现光晕的呼吸闪烁效果,通过在Unity里面创建Animation来变化这个_AllAlpha参数,可以实现想要的效果。
Unity光晕剑效果的Shader简单实现的更多相关文章
- 今天写shader流光效果,shader代码少了个括号,unity shader compiler卡死且不提示原因
今天写shader流光效果,shader代码少了个括号,unity shader compiler卡死且不提示原因 好在找到了原因,shader 代码如下,原理是提高经过的颜色亮度 void surf ...
- 【Unity Shaders】Vertex & Fragment Shader入门
写在前面 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效.这是因为我们是依赖法线和视角的点乘结果来进行描边判 ...
- unity,荧光效果(bloom)实现过程
两个月前,刚接触unity的时候费了半天劲儿做了个荧光效果(见:http://www.cnblogs.com/wantnon/p/4430749.html),今天终于抽空整理了一下,把过程写下来. 荧 ...
- Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷
Android高级控件(四)--VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷 是不是感觉QQ空间什么的每次新版本更新那炫炫的引导页就特别的激动,哈哈,其实他实现起来真的很简单很 ...
- Unity 阴影淡入淡出效果中Shader常量 unity_ShadowFadeCenterAndType和_LightShadowData的问题
由于Universal Render Pipeline目前(2020年4月1日)把阴影淡入淡出这个功能竟然给取消了…我自己拿片元位置到相机位置的距离进行了一个淡化,但是阴影边缘老是被裁切…后来研究了一 ...
- Surface Shader简单向导
Surface Shader 表面着色器 描述 当你的Material要处理光照,则一般使用Surface Shader.Surface Shader隐藏了光照的计算,你只需要在surf函数里设置好反 ...
- 解读Unity中的CG编写Shader系列十 (光滑的镜面反射(冯氏着色))
前文完成了最基本的镜面反射着色器,单平行光源下的逐顶点着色(per-vertex lighting),又称为古罗着色(Gouraud shading).这篇文章作为后续讨论更光滑的镜面反射方式,逐像素 ...
- 解读Unity中的CG编写Shader系列八(多光源漫反射)
转自http://www.itnose.net/detail/6117338.html 前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下 ...
- 解读Unity中的CG编写Shader系列三
转自http://www.itnose.net/detail/6096068.html 在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章 ...
随机推荐
- 在linux系统个人目录下安装新版python
一.下载所需的python版本文件 在linux个人目录下 下载https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tar.xz 解压tar.xz ...
- 怎么查看Eclipse的版本信息
工具/原料 Eclipse版本信息查看 第一种方法 1 找到Eclipse的解压目录就是你的Eclipse.exe 所在的目录 2 找到 .eclipseproduct 文件双击打开 3 如图 ...
- Java Synchronized的原理
我们先通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的: public class SynchronizedDemo{ public void method(){ syn ...
- 6.【应急响应】Linux入侵排查思路
0x01 入侵排查思路 一.账号安全 基本使用: 1.用户信息文件/etc/passwd root:x:0:0:root:/root:/bin/bash account:password:UID:GI ...
- 如何保持blog的高质量(相对于自己的进步而言的)
多写! 多改!! 多删!!!
- C# Object reference not set to an instance of an object.
一.问题 Object reference not set to an instance of an object. (你调用的对象是空的) 二.解决问题 在使用 c# 的查询时,先筛选后在关联其他表 ...
- validate验证注册表单
点击预览; <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...
- HBase HA + Hadoop HA 搭建
HBase 使用的是 1.2.9 的版本. Hadoop HA 的搭建见我的另外一篇:Hadoop 2.7.3 HA 搭建及遇到的一些问题 以下目录均为 HBase 解压后的目录. 1. 修改 co ...
- cogs 2123. [HZOI 2015] Glass Beads
2123. [HZOI 2015] Glass Beads ★★★ 输入文件:MinRepresentations.in 输出文件:MinRepresentations.out 简单对比时 ...
- MCP|LDY|Mass Spectrometry-based Absolute Quantification of 20S Proteasome Status for Controlled Ex-vivo Expansion of Human Adipose-derived Mesenchymal Stromal/Stem Cells(基于质谱技术的20S蛋白酶体绝对定量方法监控人体脂肪...
期刊名:Mol Cell Proteomics 发表时间:(2019年4月) IF:5.232 概述 20S蛋白酶体是一种多亚基蛋白质复合物,参与许多组织细胞生命活动过程.本研究基于SILAC标记 ...