大家好,我是阿赵。
继续说一下屏幕后处理的做法,这一期讲的是Vignette暗角效果。
一、Vignette效果介绍
Vignette暗角的效果可以给画面提供一个氛围,或者模拟一些特殊的效果。
还是拿这个角色作为底图
添加了Vignette效果后,屏幕的四边会产生一个像老式电视机一样的压暗的效果,
通过调节参数,可以做出形状比较夸张的压暗效果
如果加上闪烁和横纹之类,也可以模拟老式电影的效果。
二、实现原理
1、以屏幕中心点计算每个像素点的距离
float2 screenUV = abs(i.uv - float2(0.5f,0.5f))*_VignetteIntensity;
float dist = length(screenUV);
col.rgb *= dist;
这时候,由于屏幕靠中间的点离屏幕中心点(0.5f,0.5f)近,然后边缘的点里屏幕中心点远,所以得到的效果是中间黑,四周白。
2、给距离做power计算,让边缘形状变成接近矩形
float2 screenUV = abs(i.uv - float2(0.5f,0.5f))*_VignetteIntensity;
screenUV = pow(saturate(screenUV), _VignetteSmoothness);
float dist = length(screenUV);
col.rgb *= dist;
经过计算后,现在的黑白变成了比较接近屏幕矩形。当然,这个和pow的参数有关,调节不同的参数,可以得到不同的形状。
3、给黑白做反向
float2 screenUV = abs(i.uv - float2(0.5f,0.5f))*_VignetteIntensity;
screenUV = pow(saturate(screenUV), _VignetteSmoothness);
float dist = length(screenUV);
float vfactor = pow(saturate(1 - dist * dist), _VignetteSmoothness);
col.rgb *= vfactor;
这时候,可以看到,暗角的效果就做出来了。
三、完整代码
1、C#代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VignetteCtrl : MonoBehaviour
{
[Range(0, 3)]
public float vignetteIntensity = 1.8f;
[Range(0, 5)]
public float vignetteSmoothness = 5;
private Material vignetteMat;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (vignetteMat == null)
{
vignetteMat = new Material(Shader.Find("Hidden/AzhaoVignette"));
}
if (vignetteMat == null || vignetteMat.shader == null || vignetteMat.shader.isSupported == false)
{
return;
}
vignetteMat.SetFloat("_VignetteIntensity", vignetteIntensity);
vignetteMat.SetFloat("_VignetteSmoothness", vignetteSmoothness);
Graphics.Blit(source, destination, vignetteMat, 0);
}
}
2、Shader
Shader "Hidden/AzhaoVignette"
{
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float _VignetteIntensity;
float _VignetteSmoothness;
half4 fragVignette(v2f_img i) : SV_Target
{
half4 col = tex2D(_MainTex, i.uv);
//暗角
float2 screenUV = abs(i.uv - float2(0.5f,0.5f))*_VignetteIntensity;
screenUV = pow(saturate(screenUV), _VignetteSmoothness);
float dist = length(screenUV);
float vfactor = pow(saturate(1 - dist * dist), _VignetteSmoothness);
col.rgb *= vfactor;
return col;
}
ENDCG
Properties
{
_MainTex("Texture", 2D) = "white" {}
_VignetteIntensity("VignetteIntensity", Range(0, 3)) = 1
_VignetteSmoothness("VignetteSmoothness", Range(0, 5)) = 1
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
//0校色
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment fragVignette
ENDCG
}
}
}