Unity 屏幕特效 之 热浪扭曲效果的实现
程序员文章站
2022-07-12 23:30:27
...
Unity 屏幕特效 之 热浪扭曲效果的实现
目录
一、简介
所谓屏幕后处理,简单来说就是渲染流水线的最后阶段,对由整个场景生成的一张图片进行处理,比如HDR,运动模糊等等效果,通过屏幕空间的后处理,可以整体改变整个游戏的风格或者效果。所以,要制作屏幕后处理,我们需要两样东西,一个是用于渲染后处理效果的shader,而另一个是我们需要调用这个渲染的脚本。
实现原理:
- 使用一张噪音云图来获取随机偏移量,然后赋值给主图移动uv值来实现扭曲,实现热浪效果
二、关键技术
1、在 Shader 中,获取噪音云图的uv,赋给主图uv,并且uv随时间变化;
2、OnRenderImage函数每帧渲染完全部内容后执行,我们在每一帧设置Material的各项参数,通过Material.SetXXX("name",value)可以向shader中传递各种参数;
3、关键代码
float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _NoiseTimeScale);
float2 offset = noise.xy * _UVScale ;
return tex2D(_MainTex, i.uv + offset);
三、注意事项
1、各种后处理效果可以叠加,这里的dest并不一定就是屏幕。不过后处理是很耗费性能的,一方面是pixel shader全屏幕overdraw,另一方面,一个rendertexture的内存占用很大,尤其是大分辨率手机上,多个后处理效果可能造成内存耗尽,程序崩溃;
2、注意判断屏幕特效是否支持可以用;
3、注意参数值根据实际效果,合理调节;
四、效果预览
五、实现步骤
1、新建Unity工程,导入模型,新建脚本,如下
2、新建两个camera,Left_Camera 不挂载脚本不做处理,Right_Camera 挂在脚本做扭曲处理,两相机视口作为效果调节对比,如下
3、测试效果
4、shader 脚本
Shader "Unlit/WaveWarp"
{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_NoiseTex("Noise (RGB)", 2D) = "white" {}
_UVScale("uv scale ", Range(0.0, 1.0)) = 1.0
_NoiseTimeScale("Noise Time Scale ", Range(0,1)) = 1
}
SubShader
{
Pass{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform sampler2D _NoiseTex;
fixed _UVScale;
float _NoiseTimeScale;
fixed4 frag(v2f_img i) : COLOR
{
float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _NoiseTimeScale);
float2 offset = noise.xy * _UVScale ;
return tex2D(_MainTex, i.uv + offset);
}
ENDCG
}
}
FallBack "Diffuse"
}
5、C# 脚本
using UnityEngine;
//非运行时也触发效果
[ExecuteInEditMode]
//屏幕后处理特效一般都需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
//提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
public class ScreenPostEffectBase : MonoBehaviour
{
//Inspector面板上直接拖入
public Shader shader = null;
private Material _material = null;
public Material _Material
{
get
{
if (_material == null)
_material = GenerateMaterial(shader);
return _material;
}
}
//根据shader创建用于屏幕特效的材质
protected Material GenerateMaterial(Shader shader)
{
// 系统是否支持
if (!SystemInfo.supportsImageEffects)
{
return null;
}
if (shader == null)
return null;
//需要判断shader是否支持
if (shader.isSupported == false)
return null;
Material material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
return null;
}
void OnDisable()
{
if (_material != null)
{
DestroyImmediate(_material);
}
}
}
using UnityEngine;
public class WaveWarp : ScreenPostEffectBase
{
public Texture noiseTexure;
[Range(0.0f, 1.0f)]
public float noiseTimeScale = 1.0f;
[Range(0.0f, 1.0f)]
public float uvScale = 0.15f;
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
if (_Material != null)
{
_Material.SetFloat("_UVScale", uvScale);
_Material.SetFloat("_NoiseTimeScale", noiseTimeScale);
_Material.SetTexture("_NoiseTex", noiseTexure);
Graphics.Blit(sourceTexture, destTexture, _Material);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
}
上一篇: Unity3d之物体运动(一)
下一篇: Unity3D之物体运动(二)
推荐阅读
-
Unity3d-UGUI特效之Image的Skew变形、倾斜效果
-
Unity3D-UGUI特效之Image的高斯模糊效果
-
Unity 屏幕特效 之 热浪扭曲效果的实现
-
Unity UGUI 之 实现按钮 Button 长按和双击的功能效果
-
荐 Unity 基础 之 OnMouse 简单实现 GameObject 和 UGUI 元素随着鼠标移动,拖动的效果
-
Unity 屏幕特效 之 简单地调整颜色的 色散效果 的实现
-
Unity 屏幕特效 之 分屏之 斜角(对角线) 分屏渲染不同相机画面功能的简单实现
-
Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现
-
Unity UGUI 之 实现按钮 Button 长按和双击的功能效果
-
荐 Unity 基础 之 OnMouse 简单实现 GameObject 和 UGUI 元素随着鼠标移动,拖动的效果