效果图
目录
(2)Volumetric Sphere 用于马赛克区域的shader函数
一、利用摄像机渲染像素
在摄像机下添加一个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函数
对应的函数图:
计算体积球体并输出多个蒙版和数据。
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 Parameter Description Default Value RGB 要从sRGB(Gamma)转换为线性空间的颜色值。仅在未连接相应的输入端口时可见。 0,0,0 Mode 在准确的颜色转换方法或更快但更不准确的颜色转换方法之间切换。
- 快速sRGB到线性:从sRGB到线性的快速近似
- 精确的sRGB到线性:从sRGB到线性的更昂贵但更精确的计算
Fast sRGB to Linear
Input Port Description Type 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
}