Unity Shader-后处理:时空扭曲效果
简介
![](/assets/blank.gif)
屏幕收缩的效果
/********************************************************************FileName: PassthoughEffect.csDescription: "传说中的穿越"效果Created: 2017/05/07by :puppet_master
*********************************************************************/
using UnityEngine;public class PassthoughEffect : PostEffectBase
{//扭曲强度[Range(0, 0.15f)]public float distortFactor = 1.0f;//扭曲中心(0-1)屏幕空间,默认为中心点public Vector2 distortCenter = new Vector2(0.5f, 0.5f);void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetFloat("_DistortFactor", distortFactor);_Material.SetVector("_DistortCenter", distortCenter);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}
}
shader代码如下:
//屏幕收缩效果
//by:puppet_master
Shader "ApcShader/PaththoughEffect"{Properties {_MainTex ("Base (RGB)", 2D) = "white" {}}CGINCLUDEuniform sampler2D _MainTex;uniform float _DistortFactor; //扭曲强度uniform float4 _DistortCenter; //扭曲中心点xy值(0-1)屏幕空间#include "UnityCG.cginc"fixed4 frag(v2f_img i) : SV_Target{//计算偏移的方向float2 dir = i.uv - _DistortCenter.xy;//最终偏移的值:方向 * (1-长度),越靠外偏移越小float2 offset = _DistortFactor * normalize(dir) * (1 - length(dir));//计算采样uv值:正常uv值+从中间向边缘逐渐增加的采样距离float2 uv = i.uv + offset;return tex2D(_MainTex, uv);}ENDCGSubShader {Pass{ZTest AlwaysCull Off ZWrite OffFog { Mode off }//调用CG函数 CGPROGRAM//使效率更高的编译宏#pragma fragmentoption ARB_precision_hint_fastest //vert_img是在UnityCG.cginc中定义好的,当后处理vert阶段计算常规,可以直接使用自带的vert_img#pragma vertex vert_img#pragma fragment frag ENDCG}}
}
![](/assets/blank.gif)
![](/assets/blank.gif)
屏幕扭曲效果与收缩效果结合
/********************************************************************FileName: PassthoughEffect.csDescription: "传说中的穿越"效果Created: 2017/05/07by :puppet_master
*********************************************************************/
using UnityEngine;public class PassthoughEffect : PostEffectBase
{//收缩强度[Range(0, 0.15f)]public float distortFactor = 1.0f;//扭曲中心(0-1)屏幕空间,默认为中心点public Vector2 distortCenter = new Vector2(0.5f, 0.5f);//噪声图public Texture NoiseTexture = null;//屏幕扰动强度[Range(0, 2.0f)]public float distortStrength = 1.0f;void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortFactor", distortFactor);_Material.SetVector("_DistortCenter", distortCenter);_Material.SetFloat("_DistortStrength", distortStrength);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}
}
shader代码如下:
//屏幕收缩效果
//by:puppet_master
Shader "ApcShader/PaththoughEffect"{Properties {_MainTex ("Base (RGB)", 2D) = "white" {}_NoiseTex("Noise", 2D) = "black"{}}CGINCLUDEuniform sampler2D _MainTex;uniform sampler2D _NoiseTex;uniform float _DistortFactor; //扭曲强度uniform float4 _DistortCenter; //扭曲中心点xy值(0-1)屏幕空间uniform float _DistortStrength; #include "UnityCG.cginc"fixed4 frag(v2f_img i) : SV_Target{//计算偏移的方向float2 dir = i.uv - _DistortCenter.xy;//最终偏移的值:方向 * (1-长度),越靠外偏移越小float2 scaleOffset = _DistortFactor * normalize(dir) * (1 - length(dir));//采样Noise贴图fixed4 noise = tex2D(_NoiseTex, i.uv);//noise的权重 = 参数 * 距离,越靠近外边的部分,扰动越严重float2 noiseOffset = noise.xy * _DistortStrength * dir;//计算最终offset = 两种扭曲offset的差(取和也行,总之效果好是第一位的)float2 offset = scaleOffset - noiseOffset;//计算采样uv值:正常uv值+从中间向边缘逐渐增加的采样距离float2 uv = i.uv + offset;return tex2D(_MainTex, uv);}ENDCGSubShader {Pass{ZTest AlwaysCull Off ZWrite OffFog { Mode off }//调用CG函数 CGPROGRAM//使效率更高的编译宏#pragma fragmentoption ARB_precision_hint_fastest //vert_img是在UnityCG.cginc中定义好的,当后处理vert阶段计算常规,可以直接使用自带的vert_img#pragma vertex vert_img#pragma fragment frag ENDCG}}
}
还是上面的测试场景,这次,我们用一个噪声图,比如下图所示的这种:
![](/assets/blank.gif)
![](/assets/blank.gif)
动态的收缩和扭曲效果
/********************************************************************FileName: PassthoughEffect.csDescription: "传说中的穿越"效果Created: 2017/05/10by :puppet_master
*********************************************************************/
using UnityEngine;
using System.Collections;public class PassthoughEffect : PostEffectBase
{//收缩强度[Range(0, 0.15f)]public float distortFactor = 1.0f;//扭曲中心(0-1)屏幕空间,默认为中心点public Vector2 distortCenter = new Vector2(0.5f, 0.5f);//噪声图public Texture NoiseTexture = null;//屏幕扰动强度[Range(0, 2.0f)]public float distortStrength = 1.0f;//屏幕收缩总时间public float passThoughTime = 4.0f;//当前时间private float currentTime = 0.0f;//曲线控制权重public float curveFactor = 0.2f;//屏幕收缩效果曲线控制public AnimationCurve curve;void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortFactor", distortFactor);_Material.SetVector("_DistortCenter", distortCenter);_Material.SetFloat("_DistortStrength", distortStrength);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}//ContexMenu,可以直接在Component上右键调用该函数,比较好用的小技巧哈[ContextMenu("Play")]public void StartPassThoughEffect(){currentTime = 0.0f;StartCoroutine(UpdatePassthoughEffect());}private IEnumerator UpdatePassthoughEffect(){while(currentTime < passThoughTime){currentTime += Time.deltaTime;//根据时间占比在曲线(0,1)区间采样,再乘以权重作为收缩系数distortFactor = curve.Evaluate(currentTime / passThoughTime) * curveFactor;yield return null;//结束时强行设置为0distortFactor = 0.0f;}}}
然后呢,我们就可以来调整曲线来得到我们希望的效果啦。《耻辱》中的扭曲效果是一个缓慢加大,然后再突然恢复的一个过程,我们用曲线调整一个类似的效果,如下:
![](/assets/blank.gif)
![](/assets/blank.gif)
/********************************************************************FileName: PassthoughEffect.csDescription: "传说中的穿越"效果Created: 2017/05/10by :puppet_master
*********************************************************************/
using UnityEngine;
using System.Collections;public class PassthoughEffect : PostEffectBase
{//收缩强度[Range(0, 0.15f)]public float distortFactor = 1.0f;//扭曲中心(0-1)屏幕空间,默认为中心点public Vector2 distortCenter = new Vector2(0.5f, 0.5f);//噪声图public Texture NoiseTexture = null;//屏幕扰动强度[Range(0, 2.0f)]public float distortStrength = 1.0f;//屏幕收缩总时间public float passThoughTime = 4.0f;//当前时间private float currentTime = 0.0f;//曲线控制权重public float scaleCurveFactor = 0.2f;//屏幕收缩效果曲线控制public AnimationCurve scaleCurve;//扰动曲线系数public float distortCurveFactor = 1.0f;//屏幕扰动效果曲线控制public AnimationCurve distortCurve;void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortFactor", distortFactor);_Material.SetVector("_DistortCenter", distortCenter);_Material.SetFloat("_DistortStrength", distortStrength);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}//ContexMenu,可以直接在Component上右键调用该函数,比较好用的小技巧哈[ContextMenu("Play")]public void StartPassThoughEffect(){currentTime = 0.0f;StartCoroutine(UpdatePassthoughEffect());}private IEnumerator UpdatePassthoughEffect(){while(currentTime < passThoughTime){currentTime += Time.deltaTime;float t = currentTime / passThoughTime;//根据时间占比在曲线(0,1)区间采样,再乘以权重作为收缩系数distortFactor = scaleCurve.Evaluate(t) * scaleCurveFactor;distortStrength = distortCurve.Evaluate(t) * distortCurveFactor;yield return null;//结束时强行设置为0distortFactor = 0.0f;distortStrength = 0.0f;}}
}
各项参数以及扰动曲线设置如下图所示,噪声图换了一张其他的:
![](/assets/blank.gif)
![](/assets/blank.gif)
漩涡扭曲效果
//漩涡扭曲效果
//by:puppet_master
Shader "ApcShader/RotationDistortEffect"{Properties {_MainTex ("Base (RGB)", 2D) = "white" {}_NoiseTex("Noise", 2D) = "black"{}}CGINCLUDEuniform sampler2D _MainTex;uniform sampler2D _NoiseTex;uniform float _DistortFactor; //扭曲强度uniform float4 _DistortCenter; //扭曲中心点xy值(0-1)屏幕空间uniform float _DistortStrength; #include "UnityCG.cginc"fixed4 frag(v2f_img i) : SV_Target{//平移坐标点到中心点,同时也是当前像素点到中心的方向fixed2 dir = i.uv - _DistortCenter.xy;//计算旋转的角度:对于像素点来说,距离中心越远,旋转越少,所以除以距离。相当于用DistortFactor作为旋转的角度值Distort/180 * π,π/180 = 0.1745float rot = _DistortFactor * 0.1745 / (length(dir) + 0.001);//+0.001防止除零//计算sin值与cos值,构建旋转矩阵fixed sinval, cosval;sincos(rot, sinval, cosval);float2x2 rotmatrix = float2x2(cosval, -sinval, sinval, cosval);//旋转dir = mul(dir, rotmatrix);//再平移回原位置dir += _DistortCenter.xy;//采样noise图fixed4 noise = tex2D(_NoiseTex, i.uv);//noise的权重 = 参数 * 距离,越靠近外边的部分,扰动越严重float2 noiseOffset = noise.xy * _DistortStrength * dir;//用偏移过的uv+扰动采样MainTexreturn tex2D(_MainTex, dir + noiseOffset);}ENDCGSubShader {Pass{ZTest AlwaysCull Off ZWrite OffFog { Mode off }//调用CG函数 CGPROGRAM//使效率更高的编译宏#pragma fragmentoption ARB_precision_hint_fastest //vert_img是在UnityCG.cginc中定义好的,当后处理vert阶段计算常规,可以直接使用自带的vert_img#pragma vertex vert_img#pragma fragment frag ENDCG}}
}
C#脚本部分,仍然使用了两条曲线进行控制,一条控制旋转值,一条控制扰动值:
/********************************************************************FileName: PassthoughEffect.csDescription: 漩涡扭曲效果Created: 2017/05/10by :puppet_master
*********************************************************************/
using UnityEngine;
using System.Collections;public class RotationDistortEffect : PostEffectBase
{//收缩强度[Range(0, 20.0f)]public float distortFactor = 1.0f;//扭曲中心(0-1)屏幕空间,默认为中心点public Vector2 distortCenter = new Vector2(0.5f, 0.5f);//噪声图public Texture NoiseTexture = null;//屏幕扰动强度[Range(0, 2.0f)]public float distortStrength = 1.0f;//屏幕扭曲时间public float passThoughTime = 3.0f;//当前时间private float currentTime = 0.0f;//曲线控制权重public float rotationCurveFactor = 10.0f;//屏幕全传效果曲线控制public AnimationCurve rotationCurve;//扰动曲线系数public float distortCurveFactor = 0.1f;//屏幕扰动效果曲线控制public AnimationCurve distortCurve;void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortFactor", distortFactor);_Material.SetVector("_DistortCenter", distortCenter);_Material.SetFloat("_DistortStrength", distortStrength);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}//ContexMenu,可以直接在Component上右键调用该函数,比较好用的小技巧哈[ContextMenu("Play")]public void StartPassThoughEffect(){currentTime = 0.0f;StartCoroutine(UpdatePassthoughEffect());}private IEnumerator UpdatePassthoughEffect(){while (currentTime < passThoughTime){currentTime += Time.deltaTime;float t = currentTime / passThoughTime;//根据时间占比在曲线(0,1)区间采样,再乘以权重作为收缩系数distortFactor = rotationCurve.Evaluate(t) * rotationCurveFactor;distortStrength = distortCurve.Evaluate(t) * distortCurveFactor;yield return null;//结束时强行设置为0distortFactor = 0.0f;distortStrength = 0.0f;}}
}
配置两条曲线以及参数:
![](/assets/blank.gif)
漩涡扭曲效果动态图如下:
![](/assets/blank.gif)
Unity Shader-后处理:时空扭曲效果相关推荐
- Unity Shader 窗前雨滴效果衍生(表面水滴附着)
Unity Shader 窗前雨滴效果衍生(表面水滴附着) 霓虹中国视频截图 现实中的水珠附着效果 实现思路 1.首先创建一个Cube来作为实现效果的物体 2.创建一个Shader开始着色器的编写 实 ...
- Unity Shader·屏幕破碎效果
Unity Shader·屏幕破碎效果 前言 最近在做一个新的MMD(用Unity来实现),其中用到了一些好看的渲染技术在这里分享一下. 视频链接 https://www.bilibili.com/v ...
- Unity Shader 之 透明效果
本文引用 Unity Shader入门精要 开启透明混合后,一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值外,还有--透明度.透明度为1,则完全不透明,透明度为0,则完全不会显示. 在Unity ...
- Unity Shader - 翻书效果
今天实现一个简单的翻书的效果,话不多说,先上一张效果图: 这里就随便用的一张纹理了,我们还是称为"翻木板"吧,哈哈. 实现过程: 其实这个效果实现起来还是挺简单的,大概思路其实就是 ...
- unity shader 抖音效果
最近开始学习了unity shader,所以想要做一些简单的效果,来巩固一下知识.我第一个想做的就是做一些类似于抖音的效果.(PS:最近学习了markdown,所以就用markdown开始写博客了 ) ...
- Unity Shader 实现鬼魂效果
Shader 实现鬼魂效果 前言 前言 我们在游戏中经常会角色碰到角色的情况,大多数游戏中角色和角色重叠的时候会显示一个虚幻的鬼影而不是完全遮挡,那么这个鬼影效果怎么实现呢?接下来我们就实现这样的一个 ...
- Unity Shader - 后处理:油画效果
效果图: 效果对比图(一)
- Unity Shader 屏幕后效果——高斯模糊
高斯模糊是图像模糊处理中非常经典和常见的一种算法,也是Bloom屏幕效果的基础. 实现高斯模糊同样用到了卷积的概念,关于卷积的概念和原理详见我的另一篇博客: https://www.cnblogs.c ...
- Unity Shader 屏幕后效果——Bloom外发光
Bloom的原理很简单,主要是提取渲染图像中的亮部区域,并对亮部区域进行模糊处理,再与原始图像混合而成. 一般对亮部进行模糊处理的部分采用高斯模糊,关于高斯模糊,详见之前的另一篇博客: https:/ ...
- Unity Shader 实现磨皮效果
最近在做一些UI使用的shader,大部分是对UV进行一些操作,今天看需求文档时发现美术同学的要求里有一项是类似磨皮的效果,本来我也比较好奇这些美颜效果都是怎么做的,所以就趁此机会实验一下.查了一大堆 ...
最新文章
- python 数据增强
- Python PIL反色混合
- Tengine ngx_http_sysguard_module 过载保护模块使用
- 目标驱动的软件度量(选译)
- 模板方法模式(Template Method Pattern)学习笔记
- 前端学习(592):使用snippets辅助debugging
- 浅尝JQ AJAX
- [转]关闭不必要端口 让电脑固若金汤
- 像素生存者2为什么显示服务器不可用,像素生存者2为什么更新了玩不了 | 手游网游页游攻略大全...
- 第九期 HG255d硬件分析 《路由器就是开发板》
- BiLSTM-CRF模型理解
- R语言保存EXCEL小技巧
- 梯度消失和爆炸原因以及解决方法
- 发一个自己常用的通信词汇缩写表(实时更新)
- Ubuntu_18.04安装网易云音乐
- 建筑行业现行相关税收政策及优惠措施汇编
- 高难度c语言编程题,高难度脑筋急转弯题目合集带答案
- 云的新出路迷你云?轻松搭建私有云平台 转载7
- 7、统计字母、空格、数字 与 其它字符的个数
- 常用颜色代码表以及中国传统颜色名录