199 lines
8.2 KiB
C#
199 lines
8.2 KiB
C#
using System;
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.Universal.PostProcessing {
|
|
/// <summary>
|
|
/// Custom Post Processing injection points.
|
|
/// Since this is a flag, you can write a renderer that can be injected at multiple locations.
|
|
/// </summary>
|
|
[Flags]
|
|
public enum InjectionPoint {
|
|
/// <summary>After Opaque and Sky.</summary>
|
|
AfterOpaqueAndSky = 1,
|
|
|
|
/// <summary>Before Post Processing.</summary>
|
|
BeforePostProcess = 2,
|
|
|
|
/// <summary>After Post Processing.</summary>
|
|
AfterPostProcess = 4,
|
|
}
|
|
|
|
/// <summary>
|
|
/// The Base Class for all the custom post process renderers
|
|
/// </summary>
|
|
public abstract class CompoundRenderer : IDisposable {
|
|
private bool _initialized = false;
|
|
protected GraphicsFormat _defaultHDRFormat;
|
|
protected bool _useRGBM;
|
|
|
|
/// <summary>
|
|
/// True if you want your custom post process to be visible in the scene view. False otherwise.
|
|
/// </summary>
|
|
public virtual bool visibleInSceneView => true;
|
|
|
|
/// <summary>
|
|
/// Specifies the input needed by this custom post process. Default is Color only.
|
|
/// </summary>
|
|
public virtual ScriptableRenderPassInput input => ScriptableRenderPassInput.Color;
|
|
|
|
/// <summary>
|
|
/// Whether the function initialize has already been called
|
|
/// </summary>
|
|
public bool Initialized => _initialized;
|
|
|
|
/// <summary>
|
|
/// An intialize function for internal use only
|
|
/// </summary>
|
|
internal void InitializeInternal() {
|
|
Initialize();
|
|
_initialized = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize function, called once before the effect is first rendered.
|
|
/// If the effect is never rendered, then this function will never be called.
|
|
/// </summary>
|
|
public virtual void Initialize() {
|
|
// Texture format pre-lookup
|
|
if (SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32,
|
|
FormatUsage.Linear | FormatUsage.Render)) {
|
|
_defaultHDRFormat = GraphicsFormat.B10G11R11_UFloatPack32;
|
|
_useRGBM = false;
|
|
} else {
|
|
_defaultHDRFormat = QualitySettings.activeColorSpace == ColorSpace.Linear
|
|
? GraphicsFormat.R8G8B8A8_SRGB
|
|
: GraphicsFormat.R8G8B8A8_UNorm;
|
|
_useRGBM = true;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Setup function, called every frame once for each camera before render is called.
|
|
/// </summary>
|
|
/// <param name="renderingData">Current Rendering Data</param>
|
|
/// <param name="injectionPoint">The injection point from which the renderer is being called</param>
|
|
/// <returns>
|
|
/// True if render should be called for this camera. False Otherwise.
|
|
/// </returns>
|
|
public virtual bool Setup(in RenderingData renderingData, InjectionPoint injectionPoint) {
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called every frame for each camera when the post process needs to be rendered.
|
|
/// </summary>
|
|
/// <param name="cmd">Command Buffer used to issue your commands</param>
|
|
/// <param name="source">Source Render Target, it contains the camera color buffer in it's current state</param>
|
|
/// <param name="destination">Destination Render Target</param>
|
|
/// <param name="renderingData">Current Rendering Data</param>
|
|
/// <param name="injectionPoint">The injection point from which the renderer is being called</param>
|
|
public abstract void Render(CommandBuffer cmd, RTHandle source, RTHandle destination,
|
|
ref RenderingData renderingData, InjectionPoint injectionPoint);
|
|
|
|
/// <summary>
|
|
/// Dispose function, called when the renderer is disposed.
|
|
/// </summary>
|
|
/// <param name="disposing"> If true, dispose of managed objects </param>
|
|
public virtual void Dispose(bool disposing) { }
|
|
|
|
public void Dispose() {
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a descriptor for intermediate render targets based on the rendering data.
|
|
/// Mainly used to create intermediate render targets.
|
|
/// </summary>
|
|
/// <returns>a descriptor similar to the camera target but with no depth buffer or multisampling</returns>
|
|
public static RenderTextureDescriptor GetTempRTDescriptor(in RenderingData renderingData) {
|
|
RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
|
|
descriptor.depthBufferBits = 0;
|
|
descriptor.msaaSamples = 1;
|
|
return descriptor;
|
|
}
|
|
|
|
public static RenderTextureDescriptor GetTempRTDescriptor(in RenderingData renderingData, int width, int height,
|
|
GraphicsFormat format) {
|
|
if (width <= 0 || height <= 0) {
|
|
Debug.LogError($"Invalid parameters for GetTempRTDescriptor: {width}, {height}.");
|
|
}
|
|
|
|
RenderTextureDescriptor descriptor = GetTempRTDescriptor(renderingData);
|
|
// descriptor.graphicsFormat = format;
|
|
descriptor.width = width;
|
|
descriptor.height = height;
|
|
return descriptor;
|
|
}
|
|
|
|
public static void SetSourceSize(CommandBuffer cmd, RenderTextureDescriptor desc) {
|
|
float width = desc.width;
|
|
float height = desc.height;
|
|
if (desc.useDynamicScale) {
|
|
width *= ScalableBufferManager.widthScaleFactor;
|
|
height *= ScalableBufferManager.heightScaleFactor;
|
|
}
|
|
|
|
cmd.SetGlobalVector(ShaderConstants._SourceSize, new Vector4(width, height, 1.0f / width, 1.0f / height));
|
|
}
|
|
|
|
// Precomputed shader ids to same some CPU cycles (mostly affects mobile)
|
|
static class ShaderConstants {
|
|
public static readonly int _SourceSize = Shader.PropertyToID("_SourceSize");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use this attribute to mark classes that can be used as a custom post-processing renderer
|
|
/// </summary>
|
|
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
|
public sealed class CompoundRendererFeatureAttribute : Attribute {
|
|
// Name of the effect in the custom post-processing render feature editor
|
|
readonly string name;
|
|
|
|
// In which render pass this effect should be injected
|
|
readonly InjectionPoint injectionPoint;
|
|
|
|
// In case the renderer is added to multiple injection points,
|
|
// If shareInstance = true, one instance of the renderer will be constructed and shared between the injection points.
|
|
// Otherwise, a different instance will be constructed for every injection point.
|
|
readonly bool shareInstance;
|
|
|
|
/// <value> Name of the effect in the custom post-processing render feature editor </value>
|
|
public string Name => name;
|
|
|
|
/// <value> In which render pass this effect should be injected </value>
|
|
public InjectionPoint InjectionPoint => injectionPoint;
|
|
|
|
/// <value>
|
|
/// In case the renderer is added to multiple injection points,
|
|
/// If shareInstance = true, one instance of the renderer will be constructed and shared between the injection points.
|
|
/// Otherwise, a different instance will be constructed for every injection point.
|
|
/// </value>
|
|
public bool ShareInstance => shareInstance;
|
|
|
|
/// <summary>
|
|
/// Marks this class as a custom post processing renderer
|
|
/// </summary>
|
|
/// <param name="name"> Name of the effect in the custom post-processing render feature editor </param>
|
|
/// <param name="injectionPoint"> In which render pass this effect should be injected </param>
|
|
public CompoundRendererFeatureAttribute(string name, InjectionPoint injectionPoint, bool shareInstance = false) {
|
|
this.name = name;
|
|
this.injectionPoint = injectionPoint;
|
|
this.shareInstance = shareInstance;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the CompoundRendererFeatureAttribute attached to the type.
|
|
/// </summary>
|
|
/// <param name="type">the type on which the attribute is attached</param>
|
|
/// <returns>the attached CompoundRendererFeatureAttribute or null if none were attached</returns>
|
|
public static CompoundRendererFeatureAttribute GetAttribute(Type type) {
|
|
if (type == null) return null;
|
|
var attributes = type.GetCustomAttributes(typeof(CompoundRendererFeatureAttribute), false);
|
|
return (attributes.Length != 0) ? (attributes[0] as CompoundRendererFeatureAttribute) : null;
|
|
}
|
|
}
|
|
}
|