ShaderLab实现Vignette过场动画效果
实现Vignette过场动画效果
postprocessing中有渐晕效果(Vignette),镜头可以由边缘往中间慢慢变黑;
但是我打包WebGL的时候提示我postprocessing,GPU不支持...
so,用shaderlab实现了简单的效果,如果需要边缘模糊,就根据距离做透明度插值;
以下是效果展示:

PostEffectsBase
提供公共方法,所有的postprocess后期效果都继承该类;
Start方法中检查设备是否支持后期效果;
CheckShaderAndCreateMaterial方法检测是否支持shader,支持则创建并返回该shader的对应材质;
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class PostEffectsBase : MonoBehaviour {
// Called when start
protected void CheckResources() {
bool isSupported = CheckSupport();
if (isSupported == false) {
NotSupported();
}
}
// Called in CheckResources to check support on this platform
protected bool CheckSupport() {
if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) {
Debug.LogWarning("This platform does not support image effects or render textures.");
return false;
}
return true;
}
// Called when the platform doesn't support this effect
protected void NotSupported() {
enabled = false;
}
protected virtual void Start() {
CheckResources();
}
// Called when need to create the material used by this effect
protected Material CheckShaderAndCreateMaterial(Shader shader, Material material) {
if (shader == null) {
return null;
}
if (shader.isSupported && material && material.shader == shader)
return material;
if (!shader.isSupported) {
return null;
}
else {
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
else
return null;
}
}
}
MyVignette
根据屏幕大小,在shader的着色阶段,判断片元离屏幕中心距离和预设的半径比较,超过的全部设置成黑色(或其他);
预设半径最大值为屏幕对角线的一半;
Unity屏幕(0,0)点左下角;
温馨提示:如果要同时覆盖UI,canvas的模式不能是overlay,必须改成Camera,同时UI相机要为该脚本挂载的相机;
OnRenderImage(RenderTexture source, RenderTexture destination)
该方法为MonoBehaviour生命周期,会将屏幕渲染结果source返回,函数结束会将destination显示在屏幕上;
Graphics.Blit(source, destination, material,pass)
将source经过材质material处理后,返回destination;
pass默认为-1,计算所有pass;否则只调用索引值;
public class MyVignette : PostEffectsBase
{
public Shader vignetteShader;
private Material vignetteMaterial;
[Range(0, 1)] public float radio = 1;
public Color circleColor = Color.black;
public Vector2 screenSize;
protected override void Start()
{
base.Start();
screenSize = FindObjectOfType<CanvasScaler>().referenceResolution;
material.SetColor("_Color", circleColor);
//计算屏幕对角线一半的长度
float temp = Mathf.Sqrt(screenSize.x * screenSize.x + screenSize.y * screenSize.y)/2;
material.SetFloat("_ScreenSize", temp);
material.SetVector("_CenterPos", screenSize/2);
}
public Material material
{
get {
vignetteMaterial = CheckShaderAndCreateMaterial(vignetteShader, vignetteMaterial);
return vignetteMaterial;
}
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (material != null)
{
material.SetFloat("_Radio", radio);
Graphics.Blit(source, destination, material);
}
else
Graphics.Blit(source, destination);
}
}
VignetteShader
_MainTex 接收屏幕纹理
_Radio 接收半径变动
在MyVignette类中给Shader属性赋值,所以其实Properties中可以不用写(不用在材质中看这些值),直接pass中声明;
Shader "VignetteShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Radio("Radio",Range(0,1.0)) = 1.0
_ScreenSize("ScreenSize",Float) = 735
_CenterPos("CenterPos",vector) = (640,360,1)
_Color("CircleColor",Color) = (0,0,0,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _Radio;
fixed _ScreenSize;
float4 _CenterPos;
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//减少开方操作
float temp = (i.vertex.x - _CenterPos.x)* (i.vertex.x - _CenterPos.x)+(i.vertex.y-_CenterPos.y)*(i.vertex.y-_CenterPos.y);
_ScreenSize = _ScreenSize*_Radio;
if(temp>_ScreenSize*_ScreenSize)
col = _Color;
return col;
}
ENDCG
}
}
}
使用
主相机上挂在MyVigentte脚本,给MyVigentte参数赋值,将VignetteShader拖到MyVigentte中shader变量;
通过CanvasScaler获取屏幕宽高,Canvas的RenderMode设置成Screen Space-Camera;


代码修改MyVignette中Radio的值,就可以实现圆镜头效果;
ShaderLab实现Vignette过场动画效果的更多相关文章
- iOS过场动画调研笔记
前言 因项目须要,近期一段时间都在调研iOS的过场动画.对于我来说这是一个之前没有太涉及的领域,所以有必要把调研的过程和自己的一些理解纪录下来 为什么要自己定义过场动画? 假设大家有关注Materia ...
- [deviceone开发]-openPage的动画效果示例
一.简介do_App的openPage支持16种过场动画,这个示例直观的展示16种动画的效果.适合初学者.二.效果图三.相关下载https://github.com/do-project/code4d ...
- [deviceone开发]-打开新页动画效果
一.简介 do_App的openPage支持16种过场动画,这个示例直观的展示16种动画的效果.适合初学者. 二.效果图 三.相关下载 https://github.com/do-project/co ...
- [deviceone开发]-do_Viewshower的动画效果示例
一.简介 do_Viewshower组件也支持View之间的过场动画,支持大概12种,这个示例随机的切换12种动画中的一种,而且每次切换的动画时间不一样.直观的展示12种动画的效果.适合初学者. 二. ...
- React实现动画效果
流畅.有意义的动画对于移动应用用户体验来说是非常必要的.和React Native的其他部分一样,动画API也还在积极开发中,不过我们已经可以联合使用两个互补的系统:用于全局的布局动画LayoutAn ...
- 【Android开发日记】之基础篇(二)——Android的动画效果
什么是动画,动画的本质是通过连续不断地显示若干图像来产生“动”起来的效果.比如说一个移动的动画,就是在一定的时间段内,以恰当的速率(起码要12帧/秒以上,才会让人产生动起来的错觉)每隔若干 ...
- app引导页(背景图片切换加各个页面动画效果)
前言:不知不觉中又加班到了10点半,整个启动页面做了一天多的时间,一共有三个页面,每个页面都有动画效果,动画效果调试起来麻烦,既要跟ios统一,又要匹配各种不同的手机,然后产品经理还有可能在中途改需求 ...
- Android动画效果之自定义ViewGroup添加布局动画
前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...
- Android动画效果之Property Animation进阶(属性动画)
前言: 前面初步认识了Android的Property Animation(属性动画)Android动画效果之初识Property Animation(属性动画)(三),并且利用属性动画简单了补间动画 ...
随机推荐
- Kotlin 协程一 —— 全面了解 Kotlin 协程
一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...
- leetcode 645. 错误的集合
问题描述 集合 S 包含从1到 n 的整数.不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复. 给定一个数组 nums 代表 ...
- 字节一面:事务还没提交的时候,redolog 能不能被持久化到磁盘呢?
又是被自己菜醒的一天,总结面经看到这题目听都没听过,打开百度就像吃饭一样自然 老规矩,背诵版在文末.点击阅读原文可以直达我收录整理的各大厂面试真题 首先,咱需要明白的是,啥是持久化? 听起来高大上,换 ...
- java之类的抽取与对象的创建
Java语言之类的抽取 前言:世界由什么组成?This is a question.有人说是原子.分子,有人说是山川草木. 诚然,一千个人眼中有一千个哈姆雷特.而在程序员眼中,万物皆对象. 定义: 在 ...
- 【测试数据】android下CPU核与线程数的关系
测试方法 24MB的一张4K图片,连续计算5次直方图. 小米mix2s, 高通骁龙 845.4大核,4小核. 数据表格 线程数 绝对时间(s) 累计CPU时间(s) 每线程平均耗时(us) 每线程最大 ...
- 用Win +R运行快速启动各种程序
许多人认为Windows的Win+R运行就是摆设,除了开cmd和shutdown外毫无用处.其实Win+R是可以用于各种快捷启动的. Win+R可以视作执行一条cmd命令,要用他运行程序,理论上必须输 ...
- gin框架中的重定向
重定向redirect func someRedirect(context *gin.Context) { context.Redirect(http.StatusMovedPermanently, ...
- 南屿 带你 走进 vue
### Vue > Vue是一个前端js框架,由尤雨溪开发,是个人项目 Vue近几年来特别的受关注,三年前的时候angularJS霸占前端JS框架市场很长时间,接着react框架横空出世,因为它 ...
- 用c#实现编写esp32单片机获取DHT11温度传感器参数
欢迎爱好c#的爱好者,本文章我们将用C#的nanoframework框架来编写获取esp32单片机上的DHT11传感器的温度和湿度 实现我们需要准备配置好esp32的环境可以看看之前写的esp32搭建 ...
- Func<>用法
Func是一个委托,委托里面可以存方法,Func<string,string>或Func<string,string,int,string>等 前几个是输入参数,最后一个是返回 ...