Unity 屏幕特效 之 简单地调整颜色的 色散效果 的实现
程序员文章站
2022-05-25 08:49:55
...
Unity 屏幕特效 之 简单地调整颜色的 色散效果 的实现
目录
Unity 屏幕特效 之 简单地调整颜色的 色散效果 的实现
一、简介
所谓屏幕后处理,简单来说就是渲染流水线的最后阶段,对由整个场景生成的一张图片进行处理,比如HDR,运动模糊等等效果,通过屏幕空间的后处理,可以整体改变整个游戏的风格或者效果。所以,要制作屏幕后处理,我们需要两样东西,一个是用于渲染后处理效果的shader,而另一个是我们需要调用这个渲染的脚本。
实现原理:
- shader里片元着色器的输出颜色的rgb值是分别对rgb通道的_MainTex进行采样;
- 并对采样坐标做不同的偏移,这里主要的uv.x 上偏移;
- 如果加上时间参数,即可做出简单动画效果;
二、色散
色散是复色光分解为单色光而形成光谱的现象。色散可以利用棱镜或光栅等作用为色散系统的仪器来实现。如复色光进入棱镜后,由于它对各种频率的光具有不同折射率,各种色光的传播方向有程度的偏折,因而在离开棱镜时就各自分散,形成光谱。
三、关键技术
1、在 Shader 中,把颜色进行rgb分开处理,这里 r 和 b 上做偏移;
2、OnRenderImage函数每帧渲染完全部内容后执行,我们在每一帧设置Material的各项参数,通过Material.SetXXX("name",value)可以向shader中传递各种参数;
3、关键代码
half2 uv_0 = half2(i.uv.x - scale,i.uv.y);
half2 uv_1 = half2(i.uv.x + scale, i.uv.y);
col.r = tex2D(_MainTex, uv_0).r;
col.g = tex2D(_MainTex, i.uv).g;
col.b = tex2D(_MainTex, uv_1).b;
四、注意事项
1、各种后处理效果可以叠加,这里的dest并不一定就是屏幕。不过后处理是很耗费性能的,一方面是pixel shader全屏幕overdraw,另一方面,一个rendertexture的内存占用很大,尤其是大分辨率手机上,多个后处理效果可能造成内存耗尽,程序崩溃。
2、注意判断屏幕特效是否支持可以用
五、效果预览
六、实现步骤
1、新建Unity工程,导入模型,新建脚本,如下
2、新建两个camera,Left_Camera 不挂载脚本不做颜色处理,Right_Camera 挂在脚本做颜色处理,两相机视口作为颜色效果调节对比,如下
3、测试效果
4、Shader 脚本
Shader "Unlit/ColorDispersion"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Cull Off ZWrite Off ZTest Always
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;
float _Scale;
float _Speed;
v2f vert(appdata v){
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col= fixed4(0,0,0,1);
fixed scale = _Scale * sin(_Time.y * _Speed);
scale = saturate(scale);
half2 uv_0 = half2(i.uv.x - scale,i.uv.y);
half2 uv_1 = half2(i.uv.x + scale,i.uv.y);
col.r = tex2D(_MainTex,uv_0).r;
col.g = tex2D(_MainTex,i.uv).g;
col.b = tex2D(_MainTex,uv_1).b;
return col;
}
ENDCG
}
}
}
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;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColorDispersion : ScreenPostEffectBase
{
[Range(0, 5)]
public float scale = 1;
public float speed = 5;
void OnRenderImage(RenderTexture src, RenderTexture dest) {
if (_Material)
{
_Material.SetFloat("_Scale",scale);
_Material.SetFloat("_Speed",speed);
Graphics.Blit(src,dest,_Material);
}
else {
Graphics.Blit(src,dest);
}
}
}