后处理 逐像素的光波扩散效果

废话不多说先上效果图:

实现原理:

  1. 获取深度图
  2. 根据深度值计算出像素的NDC坐标,将结果与VP矩阵的逆矩阵相乘,再除以w分量,即可获取像素的世界坐标
  3. 再将像素的世界坐标与指定的坐标进行距离(或点乘,点乘出来的结果波纹是直线)运算
  4. 再通过时间 间隔 速度 等参数进行计算,处理上一步获取到的距离(点积)参数,进行强化
  5. 再与原始画面叠加

C#代码:

using UnityEngine;

public class WaveDiffusion_Postprocessing : MonoBehaviour
{
    public Shader waveDiffusionShader;
    public Vector4 waveCenter = Vector4.zero;         //扩散中心
    public Color waveColor = Color.red;               //波纹颜色
    public float waveSpeed = 1;                       //扩散速度
    public float waveInterval = 5;                    //扩散间隔
    public float wavePower = 10;                      //波纹强度
    public float waveColorPower = 10;                 //波纹颜色强度

    private Material waveDiffusionMat;                //渲染材质  
    private Matrix4x4 vpMatrix4x4_inverse;            //VP逆矩阵

    private void Start()
    {
        //设置相机获取深度
        Camera.main.depthTextureMode = DepthTextureMode.Depth;
        waveDiffusionMat = new Material(waveDiffusionShader);
        //计算VP逆矩阵
        Matrix4x4 vpMatrix4x4_inverse = Camera.main.projectionMatrix * Camera.main.worldToCameraMatrix;
        vpMatrix4x4_inverse = vpMatrix4x4_inverse.inverse;
        //设置矩阵
        waveDiffusionMat.SetMatrix("_VPMatrix4x4_inverse", vpMatrix4x4_inverse);
    }

    private void OnRenderImage(RenderTexture src, RenderTexture dst)
    {
        //设置渲染材质参数
        waveDiffusionMat.SetVector("_WaveCenter", waveCenter);
        waveDiffusionMat.SetFloat("_WaveSpeed", waveSpeed);
        waveDiffusionMat.SetFloat("_WaveInterval", waveInterval);
        waveDiffusionMat.SetFloat("_WavePower", wavePower);
        waveDiffusionMat.SetFloat("_WaveColorPower", waveColorPower);
        waveDiffusionMat.SetColor("_WaveColor", waveColor);
        //渲染
        Graphics.Blit(src, dst, waveDiffusionMat);
    }
}

shader代码:

Shader "Hidden/WaveDiffusion"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
	}
		SubShader
	{
		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;
			};

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}

			sampler2D _MainTex;
			sampler2D _CameraDepthTexture;
			float4x4 _VPMatrix4x4_inverse;

			float4 _WaveColor;
			float4 _WaveCenter;
			float _WaveSpeed;
			float	_WaveInterval;
			float	_WavePower;
			float	_WaveColorPower;

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				fixed depth = tex2D(_CameraDepthTexture, i.uv).r;
				fixed4 ndc = fixed4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, -depth * 2 + 1, 1);
				fixed4 worldPos = mul(_VPMatrix4x4_inverse, ndc);
				worldPos /= worldPos.w;
				float mask = 1 - Linear01Depth(depth);
				float dis = length(worldPos.xyz - _WaveCenter.xyz);
				dis -= _Time.y * _WaveSpeed;
				dis /= _WaveInterval;
				dis = dis - floor(dis);
				dis = (pow(dis, _WavePower) + pow(1 - dis, _WavePower * 4)) * 0.5;
				dis *= _WaveColorPower;
				return  dis * mask * _WaveColor + col;
			}
			ENDCG
		}
	}
}

最后:

这里我也是参考了下面几位博主的博客,想深入♂的同学可以研究下。

http://www.manew.com/thread-98405-1-1.html

https://www.jianshu.com/p/80a932d1f11e

猜你喜欢

转载自blog.csdn.net/chooselove/article/details/105413738
今日推荐