Unity ASE案例解析—Volumetric Pixelization(马赛克效果)

效果图

目录

 

一、利用摄像机渲染像素

1、ScreenAndMask 屏幕遮罩效果

(1)基础配置

(2)Volumetric Sphere 用于马赛克区域的shader函数

2、CombineLayers合并多个层级

(1)基础配置

(2)合并层级函数

Gamma To Linear Node

二、控制区域范围


一、利用摄像机渲染像素

在摄像机下添加一个Pixelize处理相机像素的代码

 

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Camera))]
[ImageEffectAllowedInSceneView]
[ExecuteInEditMode]
public class Pixelize : MonoBehaviour
{
    #region Private Members
    public Shader _screenAndMaskShader;
    public Material _screenAndMaskMaterial;
    public RenderTexture _temporaryRenderTexture;
	public Shader _combineLayersShader;
    public Material _combineLayersMaterial;
	#endregion

	#region Properties
	private Shader ScreenAndMaskShader
	{
		get
		{
			if(_screenAndMaskShader == null)
			{
				_screenAndMaskShader = Shader.Find("Hidden/PostProcess/Pixelize/ScreenAndMask");
			}

			return _screenAndMaskShader;
		}
	}
 
	private Material ScreenAndMaskMaterial
	{
		get
		{
			if(_screenAndMaskMaterial == null)
			{
				_screenAndMaskMaterial = new Material(ScreenAndMaskShader);
			}

			return _screenAndMaskMaterial;
		}
	}

	private RenderTexture TemporaryRenderTarget
	{
		get
		{
			if(_temporaryRenderTexture == null)
			{
				CreateTemporaryRenderTarget();
			}

			return _temporaryRenderTexture;
		}
	}

	private Shader CombineLayersShader
	{
		get
		{
			if(_combineLayersShader == null)
			{
				_combineLayersShader = Shader.Find("Hidden/PostProcess/Pixelize/CombineLayers");
			}

			return _combineLayersShader;
		}
	}

	private Material CombineLayersMaterial
	{
		get
		{
			if(_combineLayersMaterial == null)
			{
				_combineLayersMaterial = new Material(CombineLayersShader);
			}

			return _combineLayersMaterial;
		}
	}
	#endregion

	#region Functions
	void OnRenderImage(RenderTexture src, RenderTexture dest)
	{
		CheckTemporaryRenderTarget();
		
		Graphics.Blit(src, TemporaryRenderTarget, ScreenAndMaskMaterial);

		Graphics.Blit(TemporaryRenderTarget, dest, CombineLayersMaterial);
	}

	private void CreateTemporaryRenderTarget()
	{
		_temporaryRenderTexture = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); // better bit precision on Alpha would be preferable but 8 is enough for the current pixelization effect which is already banded
		_temporaryRenderTexture.useMipMap = true;
		_temporaryRenderTexture.autoGenerateMips = true;
		_temporaryRenderTexture.wrapMode = TextureWrapMode.Clamp;
		_temporaryRenderTexture.filterMode = FilterMode.Point;
		_temporaryRenderTexture.Create();
	}

	private void CheckTemporaryRenderTarget()
	{
		if(TemporaryRenderTarget.width != Screen.width || TemporaryRenderTarget.width != Screen.height)
		{
			ReleaseTemporaryRenderTarget();
		}
	}

	private void ReleaseTemporaryRenderTarget()
	{
		_temporaryRenderTexture.Release();
		_temporaryRenderTexture = null;
	}
	#endregion
}

主要关注这一部分:

OnRenderImage(RenderTexture,RenderTexture)

在完成所有渲染以渲染图像后,将调用OnRenderImage。

后处理效果。

它允许您通过使用基于着色器的滤镜处理最终图像来修改最终图像。传入的图像是source渲染纹理。结果应以destination渲染纹理结束 。如果覆盖此方法,则必须始终发出Graphics.Blit或渲染全屏四边形。

当相机上装有多个图像滤镜时,它们会通过将第一个滤镜的目的地作为下一个滤镜的来源,来顺序处理图像。

此消息将发送到摄像机附带的所有脚本。

 Graphics.Blit

source源纹理。
dest目标RenderTexture。将此设置null为直接在屏幕上显示。 See description for more information.

然后,

ScreenAndMaskMaterial:ScreenAndMask  shader;屏幕遮罩效果。

CombineLayersMaterial:CombineLayers shader;合并图层效果;

这两个shader 都用的是传统Legacy PostProcess shader;

1、ScreenAndMask 屏幕遮罩效果

(1)基础配置

(2)Volumetric Sphere 用于马赛克区域的shader函数

对应的函数图:

https://img-blog.csdnimg.cn/20200114154017769.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMTIwOTQ2,size_16,color_FFFFFF,t_70

计算体积球体并输出多个蒙版和数据。

2、CombineLayers合并多个层级

(1)基础配置

(2)合并层级函数

float4 color = tex2D(ScreenAndMaskTexture, UV);
SphereMask = color.w;
const float layerWidth = rcp(MaxLayers);
float previousThreshold = 0.0f;

for (int i = 1; i <= MaxLayers; ++i)
{
	float4 layerColor = tex2Dlod(ScreenAndMaskTexture, float4(UV, 0, i));
	float newThreshold = i * layerWidth;
	float mask;
	#if defined(_INTERPOLATE_LAYERS_ON)
	mask = saturate((layerColor.w - previousThreshold) / (newThreshold - previousThreshold)); // clamped inverse lerp   
	previousThreshold = newThreshold;
	#else
	mask = step(newThreshold, layerColor.w);
	#endif
	color = lerp(color, layerColor, mask);
}

return color;

Gamma To Linear Node

伽玛线性节点

Gamma到线性节点将sRGB(Gamma)空间中的颜色值转换为线性空间。
通过切换“ 精确转换”属性的开/关,可以使用精确转换方法或使用较快但精度较低的近似值来计算其输出结果。

Node ParameterDescriptionDefault Value
RGB要从sRGB(Gamma)转换为线性空间的颜色值。仅在未连接相应的输入端口时可见。0,0,0
Mode在准确的颜色转换方法或更快但更不准确的颜色转换方法之间切换。
  • 快速sRGB到线性:从sRGB到线性的快速近似
  • 精确的sRGB到线性:从sRGB到线性的更昂贵但更精确的计算
Fast sRGB to Linear
Input PortDescriptionType
RGB要从sRGB(Gamma)转换为线性空间的颜色值。Float3

二、控制区域范围

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class VolumetricSphere : MonoBehaviour
{
	#region Public Members
	[Header("Parameters")]
	[Tooltip("The radius of the sphere")]
	[Range(0.0f,50.0f)]public float radius = 3.0f;
	[Tooltip("The density of the sphere")]
	[Range(0.0f,10.0f)]public float density = 1.0f;
	[Tooltip("The curve of the fade-out")]
	[Range(0.2f,5.0f)]public float exponent = 1.0f/3.0f;
	[Tooltip("The maximum pixelization size")]
	[Range(1,10)]public int maxPixelizationLevel = 5;
	[Tooltip("Enabled the interpolation between the layers of different pixels size")]
	public bool enableLayersInterpolation = true;
	[Header("Debug")]
	[Tooltip("Outputs the sphere mask")]
	public bool debugSphere = false;
	#endregion

	#region Functions
    void Update()
    {
		Shader.SetGlobalVector("_SpherePosition", transform.position);
		Shader.SetGlobalFloat("_SphereRadius", radius);
		Shader.SetGlobalFloat("_MaskDensity", density);
		Shader.SetGlobalFloat("_MaskExponent", exponent);
		Shader.SetGlobalInt("_MaxPixelizationLevel", maxPixelizationLevel);

		if (enableLayersInterpolation)
		{
			Shader.EnableKeyword("_INTERPOLATE_LAYERS_ON");
		}
		else
		{
			Shader.DisableKeyword("_INTERPOLATE_LAYERS_ON");
		}
	    
	    if (debugSphere)
	    {
		    Shader.EnableKeyword("_DEBUG_MASK_ON");
	    }
	    else
	    {
		    Shader.DisableKeyword("_DEBUG_MASK_ON");
	    }
    }

	//void OnDrawGizmos()
	//{
	//	Color color = Color.green;
	//	color.a = 0.35f;
    //    Gizmos.color = color;		
    //    Gizmos.DrawWireSphere(transform.position, radius);
	//}
	
	void OnDrawGizmosSelected()
	{
		Gizmos.color = Color.green;		
		Gizmos.DrawWireSphere(transform.position, radius);
	}
	#endregion
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值