简介

今天来研究几个效果,最近比较忙,所以来弄几个比较简单的效果玩一下。不过也是游戏中常用的一些效果,流光效果,按照方向的溶解效果。其实这几个效果主要运用的就是世界空间坐标或者模型空间坐标用于采样的一个方法,总之就是有些非主流的纹理采样方式。不多说,下面进入正题。

流光效果

首先来看一下流光效果。流光效果是一个非常常见的效果,不仅仅是游戏,一些广告之类的也都会有这种效果。流光的原理还是比较简单的:首先就是需要一张流光图,这张流光图的大部分都是黑色,然后有一条亮线,然后我们在采样的时候,最终输出叠加上这张图的采样值,并根据时间调整采样的UV就可以有流光的效果啦。下面是一个比较简单的流光效果实现:
//流光效果
//by:puppet_master
//2017.7.29
Shader "ApcShader/FlashEffect"
{Properties{_MainTex("MainTex(RGB)", 2D) = "white" {}_FlashTex("FlashTex", 2D) = "black" {}_FlashColor("FlashColor",Color) = (1,1,1,1)_FlashSpeedX("FlashSpeedX", Range(-5, 5)) = 0_FlashSpeedY("FlashSpeedY", Range(-5, 5)) = 0.5_FlashFactor ("FlashFactor", Range(0, 5)) = 1}CGINCLUDE#include "Lighting.cginc"uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform sampler2D _FlashTex;uniform fixed4 _FlashColor;uniform fixed _FlashSpeedX;uniform fixed _FlashSpeedY;uniform fixed _FlashFactor;struct v2f {float4 pos : SV_POSITION;float3 worldNormal : NORMAL;float2 uv : TEXCOORD0;float3 worldLight : TEXCOORD1;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);return o;}fixed4 frag(v2f i) : SV_Target{half3 normal = normalize(i.worldNormal);half3 light = normalize(i.worldLight);fixed diff = max(0, dot(normal, light));fixed4 albedo = tex2D(_MainTex, i.uv);//通过时间将采样flash的uv进行偏移half2 flashuv = i.uv + half2(_FlashSpeedX, _FlashSpeedY) * _Time.y;fixed4 flash = tex2D(_FlashTex, flashuv) * _FlashColor * _FlashFactor;fixed4 c;//将flash图与原图叠加c.rgb = diff * albedo + flash.rgb;c.a = 1;return c;}ENDCGSubShader{Pass{Tags{ "RenderType" = "Opaque" }CGPROGRAM#pragma vertex vert#pragma fragment fragENDCG   }}FallBack "Diffuse"
}

shader比较简单,flashuv是随着时间逐渐增大的,这个值肯定会大于1,而正常纹理的范围是0-1,所以,要想让贴图在采样时大于0-1也有效果,我们就必须要把贴图的WrapMode设置为Repeat,否则当这个值大于1之后,边缘就被截断了,我们也就不会看到流光效果了。注意,流光的贴图是一个方向,采样uv偏移是另一个方向,比如我的流光图是水平方向的,那么流光运动的方向就是竖直方向,效果如下面动图所示:

更通用的流光效果

我们把流光shader用于一个3D模型,效果却并不像我们预期的那样会出现一条扫描线,而是亮起来的地方让人捉摸不透,如下图所示:
为什么会这样呢?其实主要是我们采样的方式导致的,正常的纹理采样都是使用uv坐标进行采样的,也就是说这个坐标是与模型有关,在这个模型上这个点需要采样纹理的哪部分是由美术展uv时决定的。我们如果用uv来进行采样,对于正常的diffuse贴图或者法线贴图等是对的,但是对于一些其他特殊的效果,uv采样不能达到我们的需求了,所以我们就需要研究一下,用一个其他的东东作为采样的坐标,这也是本篇文章主要研究的内容。
如果不用uv进行采样,那么我们就需要一些其他的值作为采样值,之前的文章我们也有使用过类似的方法,比如在热空气扭曲效果中我们使用了屏幕空间采样,采样时计算该点在屏幕空间的坐标值反过来去采样全屏GrabPass图。不过这里我们不需要屏幕空间,毕竟这样的话这个流动效果就会随着我们观察的角度而变化,所以我们选择用世界空间采样:
//流光效果
//by:puppet_master
//2017.7.30
Shader "ApcShader/FlashEffect"
{Properties{_MainTex("MainTex(RGB)", 2D) = "white" {}_FlashTex("FlashTex", 2D) = "black" {}_FlashColor("FlashColor",Color) = (1,1,1,1)_FlashFactor("FlashFactor", Vector) = (0, 1, 0.5, 0.5)_FlashStrength ("FlashStrength", Range(0, 5)) = 1}CGINCLUDE#include "Lighting.cginc"uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform sampler2D _FlashTex;uniform fixed4 _FlashColor;//改为一个vector4,减少传参次数消耗uniform fixed4 _FlashFactor;uniform fixed _FlashStrength;struct v2f {float4 pos : SV_POSITION;float3 worldNormal : NORMAL;float2 uv : TEXCOORD0;float3 worldLight : TEXCOORD1;float4 worldPos : TEXCOORD2;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//顶点转化到世界空间o.worldPos = mul(unity_ObjectToWorld, v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);return o;}fixed4 frag(v2f i) : SV_Target{half3 normal = normalize(i.worldNormal);half3 light = normalize(i.worldLight);fixed diff = max(0, dot(normal, light));fixed4 albedo = tex2D(_MainTex, i.uv);//通过时间偏移世界坐标对flashTex进行采样half2 flashuv = i.worldPos.xy * _FlashFactor.zw + _FlashFactor.xy * _Time.y;fixed4 flash = tex2D(_FlashTex, flashuv) * _FlashColor * _FlashStrength;fixed4 c;//将flash图与原图叠加c.rgb = diff * albedo + flash.rgb;c.a = 1;return c;}ENDCGSubShader{Pass{Tags{ "RenderType" = "Opaque" }CGPROGRAM#pragma vertex vert#pragma fragment fragENDCG    }}FallBack "Diffuse"
}

好了,下面我们找个帅帅哒模型,看一下修改之后的流光效果:

然后我们也可以换一张贴图,再调整一下参数,让流光换个方向:

按照方向消失或重现效果

我们再来看一个用模型空间坐标作为采样的uv的栗子,也是一种比较好玩的效果。比如我们需要一个模型身体按照一定的方向逐渐消失,直至全部消失掉的一个效果。下面说一下思路,与世界空间采样的流光效果一样,我们在vertex阶段记录一下vertex坐标,传递给fragment阶段,在fragment阶段用这个值和一个设定好的阈值进行比较,不满足条件的像素点直接discard,逐渐调整阈值,就可以得到让模型按照某个方向消失的效果了。代码如下:
//按照方向消失的效果
//by:puppet_master
//2017.8.10
Shader "ApcShader/DissolveEffectX"
{Properties{_MainTex("MainTex(RGB)", 2D) = "white" {}_DissolveVector("DissolveVector", Vector) = (0,0,0,0)}CGINCLUDE#include "Lighting.cginc"uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform float4 _DissolveVector;struct v2f {float4 pos : SV_POSITION;float3 worldNormal : NORMAL;float2 uv : TEXCOORD0;float3 worldLight : TEXCOORD1;float4 objPos : TEXCOORD2;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//顶点转化到世界空间o.objPos = v.vertex;o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);return o;}fixed4 frag(v2f i) : SV_Target{half3 normal = normalize(i.worldNormal);half3 light = normalize(i.worldLight);fixed diff = max(0, dot(normal, light));fixed4 albedo = tex2D(_MainTex, i.uv);//不满足条件的discardclip(i.objPos.xyz - _DissolveVector.xyz);fixed4 c;c.rgb = diff * albedo;c.a = 1;return c;}ENDCGSubShader{Pass{Tags{ "RenderType" = "Opaque" }CGPROGRAM#pragma vertex vert#pragma fragment fragENDCG }}FallBack "Diffuse"
}

还是上面的模型,我们逐渐调整X,Y,Z轴三个方向的阈值,就可以有逐渐消失或者出现的效果啦,如下面动图所示:


在这里,我们没有像流光效果那样使用世界空间坐标采样,而是使用了模型空间坐标采样,其实还可以使用屏幕空间坐标或者视口空间坐标采样等等,几种方式各有各的优点和缺点。使用世界空间采样,消失的方向是绝对的,比如是从上向下,那么这个模型如果趴在地上,消失的方向就会是从模型后背到前胸的方向,而且坐标阈值会随着模型处于世界中的位置不同而不同;使用模型空间采样,消失的方向与模型本身有关,比如站着的话消失方向是从头到脚,那么趴着也是从头到脚,而且坐标的阈值与模型的高矮胖瘦有关(也与模型的原点位置有点关系);使用屏幕空间采样的话,消失的方向就可能会与我们观察的方向有关,这种可能不太可控。
还有一个小问题,其实上图中的例子里面,模型从上到下,理想情况应该是调整Y轴,不过例子里面调整的确实X轴,原因应该与Unity导入之后会绕着X轴旋转90度有关,也就是原本在max里面的Y轴变成Unity里面的X轴。
下面,我们再看一下增加了边缘高亮的消失效果,为了让模消失的型边缘高亮,我们通过将用于clip的factor值与另一个高亮阈值值进行比较,如果factor小于高亮阈值,则返回一个高亮的颜色值,否则正常渲染。这样模型就总共有三种显示状态:clip状态,高亮状态,正常状态。代码如下:
//消失效果
//by:puppet_master
//2017.8.11Shader "ApcShader/DissolveEffectX"
{Properties{_Diffuse("Diffuse", Color) = (1,1,1,1)_DissolveColor("Dissolve Color", Color) = (0,0,0,0)_MainTex("Base 2D", 2D) = "white"{}_ColorFactor("ColorFactor", Range(0,1)) = 0.7_DissolveThreshold("DissolveThreshold", Float) = 0  }CGINCLUDE#include "Lighting.cginc"uniform fixed4 _Diffuse;uniform fixed4 _DissolveColor;uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform float _ColorFactor;uniform float _DissolveThreshold;  struct v2f{float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float2 uv : TEXCOORD1;float4 objPos : TEXCOORD2; };v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);o.objPos = v.vertex;  return o;}fixed4 frag(v2f i) : SV_Target{float factor = i.objPos.x - _DissolveThreshold;clip(factor); //Diffuse + Ambient光照计算fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);fixed3 lambert = saturate(dot(worldNormal, worldLightDir));fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;//等价于下面注释代码的操作fixed lerpFactor = saturate(sign(_ColorFactor - factor));return lerpFactor * _DissolveColor + (1 - lerpFactor) * fixed4(color, 1);/*if (factor < _ColorFactor){return _DissolveColor;}return fixed4(color, 1);*/}ENDCGSubShader{Tags{ "RenderType" = "Opaque" }Pass{//不让模型穿帮,关掉了背面裁剪Cull OffCGPROGRAM#pragma vertex vert#pragma fragment frag    ENDCG}}FallBack "Diffuse"
}

这一次我们只让模型在上下方向上逐渐消失,调整ColorFactor可以控制高亮区域的高度:

溶解效果进阶版

之前的文章里,我们研究过溶解效果,不过这个效果是基于全身的,我们来尝试一下,把上面按照方向消失的效果与溶解效果结合起来,做成一个按照某个方向逐渐溶解的效果。要得到随机的溶解效果,我们需要采样一张噪声图,然后在原本会直接clip掉的部分根据采样的噪声图进行clip,就能得到按照方向的溶解效果啦。
//溶解效果
//by:puppet_master
//2017.8.11Shader "ApcShader/DissolveEffectX"
{Properties{_Diffuse("Diffuse", Color) = (1,1,1,1)_DissolveColor("Dissolve Color", Color) = (1,1,1,1)_MainTex("Base 2D", 2D) = "white"{}_DissolveMap("DissolveMap", 2D) = "white"{}_DissolveThreshold("DissolveThreshold", Range(0,1)) = 0_DissolveSpeedFactor("DissolveSpeed", Range(0,5)) = 2_DissolveControl("ColorFactorB", Float) = 0}CGINCLUDE#include "Lighting.cginc"uniform fixed4 _Diffuse;uniform fixed4 _DissolveColor;uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform sampler2D _DissolveMap;uniform float _DissolveThreshold;uniform float _DissolveSpeedFactor;uniform float _DissolveControl; struct v2f{float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float2 uv : TEXCOORD1;float4 objPos : TEXCOORD2; };v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);o.objPos = v.vertex;  return o;}fixed4 frag(v2f i) : SV_Target{fixed4 dissolve = tex2D(_DissolveMap, i.uv);//Diffuse + Ambient光照计算fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);fixed3 lambert = saturate(dot(worldNormal, worldLightDir));fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;float factor = i.objPos.x - _DissolveControl;if(factor < 0){clip(_DissolveThreshold - dissolve.r * abs(factor) * _DissolveSpeedFactor);}return fixed4(color, 1);}ENDCGSubShader{Tags{ "RenderType" = "Opaque" }Pass{Cull OffCGPROGRAM#pragma vertex vert#pragma fragment frag ENDCG}}FallBack "Diffuse"
}

效果如下:


当然,也可以参考之前溶解效果,增加溶解描边高亮的效果:

Unity Shader-非主流纹理采样研究(流光,溶解,隐身效果)相关推荐

  1. unity shader立方体纹理中的反射以及折射效果的实现

    反射: 如果不考虑反射效果的话,在场景中的问题的镜面表面的效果应该是用表面的法线对立方体纹理进行采样得到该点的颜色. 所以我们进行反射的计算的时候,只需要求得反射方向,再用反射的方向对立方体纹理进行采 ...

  2. unity shader实现纹理贴图

    unity实现纹理贴图很简单,首先在appdata结构体里声明uv语义TEXCOORD0,就可以获得当前顶点的uv坐标,对外部导入的模型来说.这个uv坐标是在3d模型软件例如maya中制作模型的人预先 ...

  3. Unity Shader学习案例一: 流光效果

    Unity Shader Lab新手宝典简单Shader案例一:流光效果 + 相关基础知识说明 Shader "Samples/Light Flow"//shader名称 {Pro ...

  4. Unity Shader - GrabPass 实现武器热扭曲拖尾效果

    文章目录 先来看看效果 实现思路 Unity带的TrailRender组件 编写脚本实现 CSharp Shader 参数 注意性能 还可以优化 总结 Project 以前龙之谷喜欢选战士,帅气. 战 ...

  5. Unity Shader - 入门级 - 火烧 2D 旗帜 的溶解效果

    文章目录 需求 思路 效果 Ramp 纹理 Shader 集成到 UGUI Shader 中 Project 美术提的需求比较简单,但是之前没整过,当作记录一丢丢效果集中 需求 从图片的 下方往上 燃 ...

  6. 【Unity Shader】纹理实践4.0:简单尝试渐变纹理和遮罩纹理

    写在前面 由于我还是处于刚刚入门(其实还是小菜鸡...)的阶段,关于渐变纹理目前主要是学习一下如何通过渐变纹理控制漫反射光照. 这种用渐变纹理控制颜色效果的想法,是Valve公司(提出半兰伯特光照技术 ...

  7. Unity shader 角色消失 溶解 隐身 效果

    先上两张效果图 实现原理 一句话总结: 空间中有一个隐形的面,判断模型上和面的相对位置,根据需求隐藏上方或者下方的点. 原理就这么简单,具体怎么实现呢,首先确定数学几何中平面的性质:原点到到面上任意一 ...

  8. Unity Shader学习记录(18) —— Shader动画

    纹理动画 纹理动画在游戏中的应用非常广泛.尤其在各种资源都比较局限的移动平台上,我们往往会使用纹理动画来代替复杂的粒子系统等模拟各种动画效果. 11.2.1序列帧动画 _Time是float4类型, ...

  9. Games101结合Unity Shader入门精要学习笔记(个人向)

    第四章 3D旋转 绕X轴旋转: 绕Y轴旋转: 绕Z轴旋转: 旋转变换(一)旋转矩阵_csxiaoshui的博客-CSDN博客_旋转矩阵 重点:MVP变换!!! model transformation ...

最新文章

  1. bugzilla迁移需要修改的文件
  2. Java背景颜色怎么设成随机的_JS实现随机改变背景颜色
  3. 如何实现一套可切换的声网+阿里的直播引擎
  4. python人工智能_人工智能人才缺口千万!学Python抓住风口机会
  5. 下载旧版本jdk和tomcat
  6. UWP锁、解屏后无法响应操作
  7. mysql索引超出范围 index_输入查询条件会报参数索引超出范围的错误
  8. Pandas入门教程(一)
  9. Atitit 财政学概论 attilax学习笔记
  10. 演化博弈论----gyy参考总结
  11. Amazon IoT Core 服务成本优化
  12. centos yum安装tracert_centos6.3如何打开tracert
  13. 在华为能拿多少工资,揭秘一个真实的华为!
  14. ipsec-***过程
  15. oracle调优总结 本文转自:http://blog.csdn.net/wonth/article/details/1670366
  16. 【基于TCP的在线词典】
  17. firefly-rk3288开发板Linux驱动——LED驱动
  18. C++控制台实现简单的注册登录
  19. 苹果CMS怎么更换模板详细教程
  20. 2020华中科技大学计算机保研夏令营经验

热门文章

  1. 《世界因你而不同》摘抄与随想
  2. 十五、Jdbc操作数据库
  3. openfire 数据库倒入mySQL时ofRoster问题
  4. 判断一个数是否有小数点
  5. 微软小冰 | 接入微信公众号平台初体验
  6. debounce函数去抖实现
  7. c语言 存储管理地址转换,C语言地址的强制转换
  8. 头歌:输入输出之字母大小写转换
  9. Android 集成支付的四部曲
  10. 放大快捷键html,3D缩放的快捷键是什么?