[Unity Shader]凌波微步效果
[Unity Shader]凌波微步效果
相信很多人都看过天龙八部,里面的段誉有一个技能就是凌波微步:移动的时候人先到,衣角跟随其后。说白了就是移动时有一个残影跟着他。下面先看下最终效果
下面我们看如何实现上面的效果。
思路:
1.既然需要移动,那么就需要一个3维(x,y,z三个方向)的数据存储,同时还需要一个变量用来表示偏移强度。
2.需要一个2d贴图来做采样
因此Shader代码很快就出来了
Shader "QShader/UnlitShader_04_1"
{Properties{_MainTex ("MainTex", 2d) = "white"{}_Direction ("Direction", vector) = (0,0,0,1)}SubShader{ Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;half4 _Direction;float4 _MainTex_ST;struct appdata{float4 position : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 position : SV_POSITION;float2 uv:TEXCOORD0;};v2f vert (appdata v){v2f o;v.position.xyz += _Direction.xyz * _Direction.w;o.position = UnityObjectToClipPos(v.position);o.uv = TRANSFORM_TEX(v.uv,_MainTex);return o;}fixed4 frag (v2f i) : SV_Target{ fixed4 col = tex2D(_MainTex,i.uv);return col;}ENDCG}}
}
注意里面的 TRANSFORM_TEX 是为了即时将变化在屏幕上显示出来。
我们先看下效果
我们创建两个材质球,第一个材质球不做任何处理,然后将第二个材质球的Direction变量的X修改为2,将两个物体做个对比观察。
我们发现物体向右边移动了。接下来我们想要的残影效果还没有,我们使用噪波算法实现随机偏移的效果。
//噪波算法
float noise = frac(sin(dot(v.uv.xy, float2(12.9898, 78.233))) * 43758.5453);
我们看到物体是整体都会被拉伸了,但是我们只需要根据他的移动方向做拉伸就好,也就是他的前进方向做拉伸,背面不做拉伸。怎么做呢?
物体在阳光下会有投影,物体的投影,也就是他的反射光线是可以根据入射光线以及他的法线来算出。这里就可以将他的不做拉伸的背面理解为他的反射光线。
那么我们就将这个反射光线作为参数传入进去
//变换拉伸
fixed NdotD = max(0,dot(_Direction,v.normal));
v2f vert (appdata v){v2f o; //噪波算法float noise = frac(sin(dot(v.uv.xy, float2(12.9898, 78.233))) * 43758.5453);//变换拉伸fixed NdotD = max(0,dot(_Direction,v.normal));v.position.xyz += _Direction.xyz * _Direction.w * noise * NdotD;o.position = UnityObjectToClipPos(v.position);o.uv = TRANSFORM_TEX(v.uv,_MainTex);return o;}
实际就如上所示。至此完整的Shader代码已经出来了。我们增加了一个Color变量用来在贴图上面添加一个好看的颜色,这里仅是为了美观,可以去掉。
Shader "QShader/UnlitShader_04_2"
{Properties{_Color ("Color",Color) = (0,0,0,1)_MainTex ("MainTex", 2d) = "white"{}_Direction ("Direction", vector) = (0,0,0,1)}SubShader{ Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;half4 _Direction;float4 _MainTex_ST;float4 _Color;struct appdata{float4 position : POSITION;float2 uv : TEXCOORD0;half3 normal:NORMAL;};struct v2f{float4 position : SV_POSITION;float2 uv:TEXCOORD0;};v2f vert (appdata v){v2f o; //噪波算法float noise = frac(sin(dot(v.uv.xy, float2(12.9898, 78.233))) * 43758.5453);//变换拉伸fixed NdotD = max(0,dot(_Direction,v.normal));v.position.xyz += _Direction.xyz * _Direction.w * noise * NdotD;o.position = UnityObjectToClipPos(v.position);o.uv = TRANSFORM_TEX(v.uv,_MainTex);return o;}fixed4 frag (v2f i) : SV_Target{ fixed4 col = tex2D(_MainTex,i.uv);col+=_Color;return col;}ENDCG}}
}
这个时候我们需要一个脚本文件来将物体移动的方向作为参数传给Shader的Direction变量,用来动态显示残影。因此新建AfterglowEffect.cs代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AfterglowEffect : MonoBehaviour {private Material[] mats;private Vector3 prePosition;private Vector3 curPosition;private float deltaTime;// Use this for initializationvoid Start(){prePosition = curPosition = transform.position;Renderer[] renderers = transform.GetComponentsInChildren<Renderer>();mats = new Material[renderers.Length];for (int i = 0; i < renderers.Length; i++){Renderer renderer = renderers[i];mats[i] = renderer.sharedMaterial;}}// Update is called once per framevoid Update(){curPosition = transform.position;if (curPosition == prePosition){deltaTime = 0;return;}deltaTime += Time.deltaTime;prePosition = Vector3.Lerp(prePosition,curPosition,deltaTime);Vector3 direction = prePosition- curPosition;for (int i = 0; i < mats.Length; i++){mats[i].SetVector("_Direction", new Vector4(direction.x, direction.y, direction.z, mats[i].GetVector("_Direction").w));}}
}
这里有两个需要注意的地方
prePosition = Vector3.Lerp(prePosition,curPosition,deltaTime);
我们根据之前的位置和当前的位置通过Lerp函数做插值,动态传入就让残影移动的比较平滑。还有一个要注意的是我们的移动方向
Vector3 direction = prePosition- curPosition;
一般情况下移动方向是新位置减去之前的位置,但是这样会导致残影优先移动了过去,什么意思呢?就是下面这个情况
我们的移动方向是向右边,但是残影的方向其实应该是向左边,也就是反过来,这样才是对的。
参考:https://connect.unity.com/p/shaderan-li-ding-dian-yun-dong-mo-hu
欢迎关注微信公众号:Unity游戏开发笔记
QQ群:
[Unity Shader]凌波微步效果相关推荐
- Unity Shader 动画效果出现残影
问题 复现<Unity Shader入门精要>的动画效果时,我发现我的动画都出现了残影. 一开始认为是程序写错了,采样出现了问题,但是复查对比其他资料很多遍也没发现错误. 解决方法 后来反 ...
- Unity Shader放大镜效果
小菜最近看到了一篇关于Shader实现的放大镜效果,酷炫的效果让小菜倍生好奇,冲动之下还是搬来练练手,刚好巩固下自己的顶点片元着色器编码. 有没有想学习的冲动!!! 文章的开始先来介绍一款好用的vs编 ...
- Unity Shader 新手引导效果
这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下. 1.圆形镂空shader代码: //计算片元世界坐标和目标中心位置的距离 float dis = distance(IN.worldP ...
- unity Shader 扭曲效果
原理 所谓扭曲就是扰动一个物体的uv坐标,表现出来就是一个扰动效果,如火焰扭曲空气,和水波对水底的影响. 1. 在shader 中我们需要一张当前渲染的纹理 2. 给一个物体渲染并使用当前纹理,用屏幕 ...
- Unity Shader - 描边效果
原文链接:http://blog.csdn.net/puppet_master/article/details/54000951 简介 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个 ...
- Unity Shader透明效果
在实时渲染中要实现透明效果,通常会在渲染模型时控制他的透明通道.当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值之外,它还有另一个属性--透明度.当透明度为1时表示该像素是完全 ...
- Unity Shader 贴花效果(一)
本文实现的是一个Mesh Decal方法的贴花方案,参考了本篇博文链接: unity的贴花方案.链接的文章是转载的,我并没有找到原文地址.本篇文章主要是学习和自己的理解为主. 先看未贴花之前的效果 这 ...
- 【Unity Shader 消融效果_案例分享】
1.实现逻辑 消融效果主要是利用了Shader中的clip()函数,也就是透明测试功能,在ASE中叫"Opacity Mask". 消融效果是基于一张"Noise&quo ...
- 【Unity Shader 描边效果_案例分享】
1.实现逻辑 描边效果Shader有多种实现方式,可以通过后处理和MatCap实现. 这次主要想展示的是通过两个Pass实现. 当Shader中有多个Pass时,渲染流程会安装顺序依次执行,于是后面的 ...
最新文章
- Caffe实战二(手写体识别例程:CPU、GPU、cuDNN速度对比)
- mysql提高缓存_合理配置MySQL缓存 提高缓存命中率
- IAR切BANK--程序中的使用
- 第七篇:Spring Boot整合Thymeleaf_入门试炼02
- tortoisegit 代码的回滚方式 --两种
- 关于架设流媒体服务器与DRM加密问题
- SpringCloud之实现下载Excel模板文件
- 网络营销:信任是流量时代的蓝海
- 2021年海河英才计划天津落户天津最详细过程
- Icarus主题美化
- 【Python】计算文件的MD5、SHA1、SHA256值(校验文件完整性)
- Fidder基础知识
- 在html里如何下雪花,html加动态雪花
- Java获取项目当前请求的全部URL,Java获取Referer,Java获取完整链接地址URL
- Oracle数据库安装容易出错问题的解决方案
- linux与windows文件互传(scp指令)
- navicat12连接SQL Server时出错:未发现数据源名称并且未指定默认驱动程序
- 软件工程 - 基于UML的面向对象设计报告模板
- dreamweaver (dw)cc 2017
- Job for network.service failed虚拟机无法重启网络问题详解
热门文章
- python中不可变数据类型有_Python中的可变数据类型有____,不可变数据类型有____。_学小易找答案...
- Java基础-this关键字
- MySQL高级篇知识点——索引优化与查询优化
- List集合的迭代神器ListIterator
- {练习题}函数(3)
- Get一个全新的网盘工具5T的OneDrive(如何领取免费的5T空间的OneDrive和Office)
- 如何优雅的对 Docker 容器进行健康检查
- 【鱼眼相机模型】鱼眼相机投影模型理解
- 一文辨析 Java、JSP、JavaScript
- linux date 时间同步,Linux date 时间设置同步命令分享