First Commit
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a bunch of named RenderTexture for the camera that can then be used by other
|
||||
/// render passes.
|
||||
/// The textures can be used, for example, as a temporary texture when operating on the
|
||||
/// camera colour texture and then copying it back - saving the pass having to create
|
||||
/// its own texture. Another example is that the textures can be used to pass result between
|
||||
/// passes - since these temporary textures will be around from the time they are created to
|
||||
/// the end of the render pipeline.
|
||||
///
|
||||
/// Other passes should access the textures via the static interface this class
|
||||
/// provides.
|
||||
///
|
||||
/// NOTE: names are converted to integer hashes to save doing string operations every frame.
|
||||
/// </summary>
|
||||
public class TemporaryCameraCopyTextureRenderFeature : ScriptableRendererFeature
|
||||
{
|
||||
[SerializeField]
|
||||
private RenderPassEvent m_WhenToAdd = RenderPassEvent.BeforeRendering;
|
||||
|
||||
[SerializeField]
|
||||
private List<string> m_TextureNames;
|
||||
|
||||
private TemporaryCameraTextureRenderPass m_Pass;
|
||||
|
||||
private readonly Dictionary<int, RenderTargetIdentifier> m_NameHashToTargetIdentifierMap =
|
||||
new Dictionary<int, RenderTargetIdentifier>();
|
||||
|
||||
private readonly List<NameHashShaderIdPair> m_NameHashesAndIds = new List<NameHashShaderIdPair>();
|
||||
|
||||
public struct NameHashShaderIdPair
|
||||
{
|
||||
public int m_NameHash;
|
||||
public int m_ShaderId;
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
if (s_HasInstance && s_Instance != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_HasInstance = true;
|
||||
s_Instance = this;
|
||||
|
||||
//
|
||||
// Create the name hashes
|
||||
//
|
||||
m_NameHashesAndIds.Clear();
|
||||
for (int i = 0; i < m_TextureNames.Count; i++)
|
||||
{
|
||||
m_NameHashesAndIds.Add( new NameHashShaderIdPair()
|
||||
{
|
||||
m_NameHash = GetNameHash(m_TextureNames[i]),
|
||||
m_ShaderId = Shader.PropertyToID(m_TextureNames[i]),
|
||||
});
|
||||
}
|
||||
|
||||
m_Pass = new TemporaryCameraTextureRenderPass();
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (m_Pass == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if ENABLE_VR
|
||||
var isXR = XRSettings.enabled;
|
||||
m_Pass.Setup(m_WhenToAdd, isXR, m_NameHashesAndIds, SetupTempTargetIdentifier, ClearTempTargetIdentifiers);
|
||||
#else
|
||||
m_Pass.Setup(m_WhenToAdd, false, m_NameHashesAndIds, SetupTempTargetIdentifier, ClearTempTargetIdentifiers);
|
||||
#endif
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (s_Instance == this)
|
||||
{
|
||||
s_HasInstance = false;
|
||||
s_Instance = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
|
||||
private bool InternalTryGetTempTextureIdentifier(int nameHash, out RenderTargetIdentifier outTargetIdentifier)
|
||||
{
|
||||
return m_NameHashToTargetIdentifierMap.TryGetValue(nameHash, out outTargetIdentifier);
|
||||
}
|
||||
|
||||
private void InternalClearTempTargetIdentifiers()
|
||||
{
|
||||
m_NameHashToTargetIdentifierMap.Clear();
|
||||
}
|
||||
|
||||
private void InternalSetupTempTargetIdentifier(int nameHash, RenderTargetIdentifier identifier)
|
||||
{
|
||||
m_NameHashToTargetIdentifierMap[nameHash] = identifier;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Static interface
|
||||
//
|
||||
//
|
||||
public const int k_InvalidNameHash = -1;
|
||||
private static bool s_HasInstance;
|
||||
private static TemporaryCameraCopyTextureRenderFeature s_Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Used by passes to ask for a named texture by its name hash.
|
||||
/// NOTE: hashes are used to avoid having a dictionary keyed by strings.
|
||||
/// </summary>
|
||||
/// <param name="nameHash"></param>
|
||||
/// <param name="outTargetIdentifier"></param>
|
||||
/// <returns>true if the texture is available, false otherwise</returns>
|
||||
public static bool TryGetTempTextureIdentifier(int nameHash, out RenderTargetIdentifier outTargetIdentifier)
|
||||
{
|
||||
if (!s_HasInstance)
|
||||
{
|
||||
outTargetIdentifier = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
return s_Instance.InternalTryGetTempTextureIdentifier(nameHash, out outTargetIdentifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a name, this returns the hash of that name.
|
||||
/// </summary>
|
||||
public static int GetNameHash(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return k_InvalidNameHash;
|
||||
}
|
||||
|
||||
return name.GetHashCode();
|
||||
}
|
||||
|
||||
private static void SetupTempTargetIdentifier(int nameHash, RenderTargetIdentifier identifier)
|
||||
{
|
||||
if (!s_HasInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_Instance.InternalSetupTempTargetIdentifier(nameHash, identifier);
|
||||
}
|
||||
|
||||
private static void ClearTempTargetIdentifiers()
|
||||
{
|
||||
if (!s_HasInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_Instance.InternalClearTempTargetIdentifiers();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private bool m_EditorNameHashToTargetIdentifierMapFoldout;
|
||||
private bool m_EditorNameHashesAndIdsFoldout;
|
||||
protected virtual void EditorOnInspectorGUIAfterBase()
|
||||
{
|
||||
EditorGUILayout.LabelField("Info", EditorStyles.boldLabel);
|
||||
|
||||
var origIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel += 1;
|
||||
#if false
|
||||
//
|
||||
// NOTE:
|
||||
// m_NameHashToTargetIdentifierMap gets cleared every frame so no useful info
|
||||
//
|
||||
m_EditorNameHashToTargetIdentifierMapFoldout = EditorGUILayout.Foldout(m_EditorNameHashToTargetIdentifierMapFoldout, "Name hash to identifier map");
|
||||
if (m_EditorNameHashToTargetIdentifierMapFoldout)
|
||||
{
|
||||
|
||||
foreach (var nameHashIdentifier in m_NameHashToTargetIdentifierMap)
|
||||
{
|
||||
EditorGUILayout.LabelField(
|
||||
$"Name hash: {nameHashIdentifier.Key}, identifier {nameHashIdentifier.Value}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_EditorNameHashesAndIdsFoldout = EditorGUILayout.Foldout(m_EditorNameHashesAndIdsFoldout, "Name hash to shader id map");
|
||||
if (m_EditorNameHashesAndIdsFoldout)
|
||||
{
|
||||
foreach (var nameHashIds in m_NameHashesAndIds)
|
||||
{
|
||||
EditorGUILayout.LabelField(
|
||||
$"Name hash: {nameHashIds.m_NameHash}, identifier {nameHashIds.m_ShaderId}");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField("Instance", s_Instance, typeof(TemporaryCameraCopyTextureRenderFeature), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUI.indentLevel = origIndent;
|
||||
|
||||
EditorGUILayout.LabelField("Controls", EditorStyles.boldLabel);
|
||||
}
|
||||
|
||||
private static void EditorTextureNameAndHash(string label, string namedTemporaryName, int namedTemporaryNameHash)
|
||||
{
|
||||
EditorGUILayout.TextField(label);
|
||||
EditorGUI.indentLevel += 1;
|
||||
if (!string.IsNullOrEmpty(namedTemporaryName))
|
||||
{
|
||||
EditorGUILayout.IntField(namedTemporaryName, namedTemporaryNameHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.IntField("null name", namedTemporaryNameHash);
|
||||
}
|
||||
EditorGUI.indentLevel -= 1;
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(TemporaryCameraCopyTextureRenderFeature))]
|
||||
private class TemporaryCameraCopyTextureRenderFeatureEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
var me = target as TemporaryCameraCopyTextureRenderFeature;
|
||||
if (me != null)
|
||||
{
|
||||
me.EditorOnInspectorGUIAfterBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the pass that creates the named textures.
|
||||
/// </summary>
|
||||
public class TemporaryCameraTextureRenderPass : ScriptableRenderPass
|
||||
{
|
||||
private bool m_IsXR;
|
||||
private List<TemporaryCameraCopyTextureRenderFeature.NameHashShaderIdPair> m_NameHashesAndIds;
|
||||
private Action<int, RenderTargetIdentifier> m_SetIdentifierAction;
|
||||
private Action m_ClearIdentifiersAction;
|
||||
|
||||
public void Setup(RenderPassEvent whenToRender, bool isXR,
|
||||
List<TemporaryCameraCopyTextureRenderFeature.NameHashShaderIdPair> nameHashesAndIds, Action<int, RenderTargetIdentifier> setIdentifierAction,
|
||||
Action clearIdentifiersAction)
|
||||
{
|
||||
renderPassEvent = whenToRender;
|
||||
m_IsXR = isXR;
|
||||
m_NameHashesAndIds = nameHashesAndIds;
|
||||
m_SetIdentifierAction = setIdentifierAction;
|
||||
m_ClearIdentifiersAction = clearIdentifiersAction;
|
||||
}
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
//
|
||||
// Create the temporary textures
|
||||
//
|
||||
#if UNITY_SWITCH
|
||||
var renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
|
||||
var width = 1280;
|
||||
var height = 720;
|
||||
#elif ENABLE_VR
|
||||
var renderTextureDescriptor = m_IsXR ? XRSettings.eyeTextureDesc : renderingData.cameraData.cameraTargetDescriptor;
|
||||
#else
|
||||
var renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
|
||||
#endif
|
||||
for (int i = 0; i < m_NameHashesAndIds.Count; i++)
|
||||
{
|
||||
#if UNITY_SWITCH
|
||||
cmd.GetTemporaryRT(m_NameHashesAndIds[i].m_ShaderId, width,height,renderTextureDescriptor.depthBufferBits,FilterMode.Bilinear,renderTextureDescriptor.colorFormat);
|
||||
#else
|
||||
cmd.GetTemporaryRT(m_NameHashesAndIds[i].m_ShaderId, renderTextureDescriptor);
|
||||
#endif
|
||||
m_SetIdentifierAction?.Invoke(m_NameHashesAndIds[i].m_NameHash, new RenderTargetIdentifier(m_NameHashesAndIds[i].m_ShaderId));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnCameraCleanup(CommandBuffer cmd)
|
||||
{
|
||||
m_ClearIdentifiersAction?.Invoke();
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45f2fc87cae84acca393898ba15c1861
|
||||
timeCreated: 1645691226
|
||||
Reference in New Issue
Block a user