First Commit
This commit is contained in:
8
Assets/Scripts/RenderPasses/AlbertGhostMemory.meta
Normal file
8
Assets/Scripts/RenderPasses/AlbertGhostMemory.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b585bdb3bfb92934ca182246382c6662
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,117 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class AlbertGhostMemory : ScriptableRendererFeature
|
||||
{
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_IsEnabled;;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_IsEnabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private bool m_IsEnabled = true;
|
||||
|
||||
|
||||
[FormerlySerializedAs("m_Settings")]
|
||||
[SerializeField] private AlbertGhostMemorySettings m_FallbackSettings;
|
||||
|
||||
[FormerlySerializedAs("m_AlbertGhostMemoryCompositeSettings")]
|
||||
[SerializeField] private AlbertGhostMemoryCompositeSettings m_FallbackCompositeSettings;
|
||||
|
||||
/// <summary>
|
||||
/// The material used for the ghost effect.
|
||||
/// NOTE: the shader is expected to provide the "_PerGhostAlpha" property to set the per object
|
||||
/// alpha.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Material m_GhostMaterial;
|
||||
|
||||
/// <summary>
|
||||
/// The material used to blur the ghosts.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Material m_BlurMaterial;
|
||||
|
||||
private AlbertGhostMemoryPass m_Pass;
|
||||
|
||||
private AlbertGhostMemorySettings m_SettingsLoader;
|
||||
private AlbertGhostMemoryCompositeSettings m_CompositeSettingsLoader;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
bool forceFallback = false;
|
||||
#if UNITY_EDITOR
|
||||
//
|
||||
// Cannot use Addressables in editor outside of playmode so use fallback
|
||||
//
|
||||
forceFallback = !EditorApplication.isPlayingOrWillChangePlaymode;
|
||||
#endif
|
||||
|
||||
//m_SettingsLoader
|
||||
|
||||
//m_CompositeSettingsLoader
|
||||
|
||||
// This pass uses the depth buffer hence it should be executed after Unity's CopyDepth pass.
|
||||
m_Pass = new AlbertGhostMemoryPass(RenderPassEvent.AfterRenderingSkybox + 1,
|
||||
m_GhostMaterial, m_BlurMaterial);
|
||||
|
||||
}
|
||||
|
||||
private void DebugSetEnabledState(bool state)
|
||||
{
|
||||
m_IsEnabled = state;
|
||||
}
|
||||
private bool DebugGetEnabledState()
|
||||
{
|
||||
return m_IsEnabled;
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (m_Pass == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// zeroing here in case the pass is not added
|
||||
//
|
||||
GhostObjectCollection.Instance.NumberOfObjectsRendered = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
m_Pass.SetSettings(m_FallbackSettings, m_FallbackCompositeSettings);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var ghostObjectBehaviours = GhostObjectCollection.Instance.GhostObjectBehaviours;
|
||||
var render = GhostObjectCollection.Instance.HasSomethingToRender();
|
||||
|
||||
if (!render || !m_IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Pass.Setup(renderingData.cameraData.camera, renderer.cameraColorTarget, ghostObjectBehaviours);
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6ff8b75980439440b930f9f955cac1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2f4087f258649684b9620322674cf675, type: 3}
|
||||
m_Name: AlbertGhostMemoryCompositeSettings
|
||||
m_EditorClassIdentifier:
|
||||
m_EdgeValue: 0.045
|
||||
m_ChromaticAberration: 0.0005
|
||||
m_ChromaticAberrationSpeed: 0.5
|
||||
m_Brightness: 0.5
|
||||
m_Contrast: 1
|
||||
m_Alpha: 0.5
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1b89dc39ee21574dae98ffc6243bb81
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,481 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper methods for ScriptableRenderPasses
|
||||
/// </summary>
|
||||
public static class ScriptableRenderPassHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper method to create new Engine material with specified Shader
|
||||
/// </summary>
|
||||
public static void CreateMaterial(string shaderPath, out Material mat)
|
||||
{
|
||||
mat = default;
|
||||
if (TryGetShader(out var shader, shaderPath))
|
||||
{
|
||||
mat = new Material(shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to load shader {shaderPath}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for Shader.Find
|
||||
/// </summary>
|
||||
/// <returns>True if Shader was found and loaded</returns>
|
||||
private static bool TryGetShader(out Shader shader, string path)
|
||||
{
|
||||
shader = default;
|
||||
shader = Shader.Find(path);
|
||||
return shader != null;
|
||||
}
|
||||
}
|
||||
|
||||
public class AlbertGhostMemoryPass : ScriptableRenderPass
|
||||
{
|
||||
private const string k_ProfilerIdent = "GhostPass";
|
||||
|
||||
#region Ident Consts
|
||||
private const string k_AlbertGhostMemoryMaskTex = "_AlbertGhostMemoryMaskTex";
|
||||
private const string k_AlbertGhostMemoryTex = "_AlbertGhostMemoryTex";
|
||||
private const string k_AlbertGhostMemoryBlurredTex = "_AlbertGhostMemoryBlurredTex";
|
||||
private const string k_TempTexGhost = "_TempTexGhost";
|
||||
private const string k_MainText = "_MainTex";
|
||||
private const string k_PerGhostAlphaProperty = "_PerGhostAlpha";
|
||||
#endregion Ident Consts
|
||||
|
||||
#region Render Texture IDs
|
||||
private readonly int m_MaskRenderTexID = Shader.PropertyToID(k_AlbertGhostMemoryMaskTex);
|
||||
private readonly int m_MemoryRenderTexID = Shader.PropertyToID(k_AlbertGhostMemoryTex);
|
||||
private readonly int m_BlurPassRenderTexID = Shader.PropertyToID(k_AlbertGhostMemoryBlurredTex);
|
||||
private readonly int m_TempRenderTexID = Shader.PropertyToID(k_TempTexGhost);
|
||||
#endregion Render Texture IDs
|
||||
|
||||
#region Shader Properties
|
||||
private readonly int k_PerGhostAlphaPropertyId = Shader.PropertyToID(k_PerGhostAlphaProperty);
|
||||
private readonly int m_LightDirectionID = Shader.PropertyToID("_LightDirection");
|
||||
private readonly int m_LightColourID = Shader.PropertyToID("_LightColour");
|
||||
private readonly int m_BlurResolution = Shader.PropertyToID("_BlurResolution");
|
||||
private readonly int m_BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
private readonly int m_BlurDirectionX = Shader.PropertyToID("_BlurDirectionX");
|
||||
private readonly int m_BlurDirectionY = Shader.PropertyToID("_BlurDirectionY");
|
||||
#endregion
|
||||
|
||||
private RenderTargetIdentifier m_CameraColorTargetIdent;
|
||||
|
||||
/// <summary>
|
||||
/// All the actively registered GhostObjectBehaviours
|
||||
/// Passed down via GhostObject Collection
|
||||
/// </summary>
|
||||
private IList<GhostObjectBehaviour> m_GhostObjectBehaviours;
|
||||
|
||||
private MaterialPropertyBlock m_MaterialPropertyBlock = new MaterialPropertyBlock();
|
||||
|
||||
private AlbertGhostMemoryCompositeSettings m_AlbertGhostMemoryCompositeSettings;
|
||||
|
||||
private Material m_MemoryMaterial;
|
||||
private Material m_BlurMaterial;
|
||||
|
||||
private Camera m_Camera;
|
||||
private Vector3 m_LightDirection = new Vector3(1.0f, 1.0f, 0.0f);
|
||||
private Color m_LightColour = Color.white;
|
||||
|
||||
/// <summary>
|
||||
/// The uniform Blur texture size, calculated from the current screen size
|
||||
/// </summary>
|
||||
private int m_BlurRes;
|
||||
|
||||
/// <summary>
|
||||
/// Effects how far off centre each Blur sample becomes
|
||||
/// </summary>
|
||||
private float m_BlurRad = 1.5f;
|
||||
|
||||
/// <summary>
|
||||
/// The number of Blur passes performed.
|
||||
/// This effects ALL objects rendered
|
||||
/// </summary>
|
||||
#if UNITY_SWITCH
|
||||
private int m_BlurPasses = 0;
|
||||
#else
|
||||
private int m_BlurPasses = 4;
|
||||
#endif
|
||||
|
||||
//private GameSettings m_GameSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Used in DrawObjectsXYZ. We use this in conjunction with GetSharedMaterials.
|
||||
/// Avoids GC alloc from .sharedMaterials
|
||||
/// </summary>
|
||||
private readonly List<Material> m_SharedMaterials = new List<Material>();
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private readonly HashSet<Renderer> m_EditorLoggedNullMaterialRenderers = new HashSet<Renderer>();
|
||||
#endif
|
||||
|
||||
public bool HasSettings { get; private set; }
|
||||
|
||||
public AlbertGhostMemoryPass(RenderPassEvent whenToInsert,
|
||||
Material memoryMaterial, Material blurMaterial)
|
||||
{
|
||||
renderPassEvent = whenToInsert;
|
||||
|
||||
//
|
||||
// NOTE: the materials are passed in instead of being loaded to avoid the shader not
|
||||
// being available via Shader.Find() when the shader has changed and Unity first opens.
|
||||
//
|
||||
m_MemoryMaterial = memoryMaterial; //TODO TOBY: replace with one found on the object / the test fake TestFakeAlvertGhostMemoryCmdShader
|
||||
m_BlurMaterial = blurMaterial;
|
||||
|
||||
// grab the game setting for blur passes and use it here.
|
||||
|
||||
//Disabled for the sample
|
||||
//GameSettings.GetSlowStartSystem(HandleGameSettings, out m_GameSettings, true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private void HandleGameSettings(GameSettings system, SlowSystemState state)
|
||||
{
|
||||
m_GameSettings = system;
|
||||
if (system == null) return;
|
||||
|
||||
if (!system.TryGetValue(GameSettingsKeys.k_NumGhostBlurPasses, out int value)) return;
|
||||
|
||||
m_BlurPasses = value;
|
||||
|
||||
m_GameSettings.AddListenOnGameSettingChange(GameSettingsKeys.k_NumGhostBlurPasses, OnSettingChanged, true);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void OnSettingChanged( int value)
|
||||
{
|
||||
m_BlurPasses = value;
|
||||
}
|
||||
|
||||
public void SetSettings(AlbertGhostMemorySettings settings, AlbertGhostMemoryCompositeSettings albertGhostMemoryCompositeSettings)
|
||||
{
|
||||
m_LightColour = settings.LightColour;
|
||||
m_LightDirection = settings.LightDirection;
|
||||
m_BlurRad = settings.BlurRadius;
|
||||
m_BlurRes = settings.BlurTextureResolution;
|
||||
|
||||
m_AlbertGhostMemoryCompositeSettings = albertGhostMemoryCompositeSettings;
|
||||
|
||||
HasSettings = true;
|
||||
}
|
||||
|
||||
#region ScriptableRenderPass
|
||||
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
||||
{
|
||||
if (!HasSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to make RTs for XR, otherwise use Default Settings
|
||||
//
|
||||
if (!ConfigureTemporaryRenderTexturesForXR(in cmd)) ConfigureTemporaryRenderTextures(in cmd);
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
if (!HasSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//
|
||||
// Reset the number of objects renderer, this is a new pass
|
||||
//
|
||||
GhostObjectCollection.Instance.NumberOfObjectsRendered = 0;
|
||||
var cmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
cmd.Clear();
|
||||
|
||||
SetAllShaderParameters(in cmd);
|
||||
|
||||
DrawObjectsDefault(in cmd);
|
||||
|
||||
//
|
||||
// Only bother we the rest of the process if we actually
|
||||
// rendered anything using default materials
|
||||
//
|
||||
if (GhostObjectCollection.Instance.NumberOfObjectsRendered > 0)
|
||||
{
|
||||
DrawObjectsMemory(in cmd);
|
||||
BlurMask(in cmd);
|
||||
|
||||
// make sure to set the render target back to the main camera!
|
||||
CoreUtils.SetRenderTarget(cmd, m_CameraColorTargetIdent);
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
}
|
||||
|
||||
//cmd.Clear();
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
|
||||
public override void FrameCleanup(CommandBuffer cmd)
|
||||
{
|
||||
if (!HasSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cmd.ReleaseTemporaryRT(m_MemoryRenderTexID);
|
||||
cmd.ReleaseTemporaryRT(m_MaskRenderTexID);
|
||||
cmd.ReleaseTemporaryRT(m_BlurPassRenderTexID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Setup(Camera camera, RenderTargetIdentifier cameraColorTargetIdent, List<GhostObjectBehaviour> ghostObjectBehaviours)
|
||||
{
|
||||
m_Camera = camera;
|
||||
m_CameraColorTargetIdent = cameraColorTargetIdent;
|
||||
m_GhostObjectBehaviours = ghostObjectBehaviours;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets Global and local variables used
|
||||
/// across various shaders in the process
|
||||
/// </summary>
|
||||
private void SetAllShaderParameters(in CommandBuffer commandBuffer)
|
||||
{
|
||||
commandBuffer.SetGlobalVector(m_LightDirectionID, m_LightDirection);
|
||||
commandBuffer.SetGlobalColor(m_LightColourID, m_LightColour);
|
||||
commandBuffer.SetGlobalFloat(m_BlurResolution, m_BlurRes);
|
||||
commandBuffer.SetGlobalFloat(m_BlurRadius, m_BlurRad);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all GhostObjects either with
|
||||
/// Default materials or with the Ghost Material
|
||||
/// </summary>
|
||||
private void DrawAllObjects(in CommandBuffer commandBuffer, bool useMemoryMaterial = false)
|
||||
{
|
||||
if (m_GhostObjectBehaviours == null) return;
|
||||
|
||||
for (int i = 0, counti = m_GhostObjectBehaviours.Count; i < counti; ++i)
|
||||
{
|
||||
var ghostObjectBehaviour = m_GhostObjectBehaviours[i];
|
||||
if (ghostObjectBehaviour == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var ghostObject = ghostObjectBehaviour.GhostObject;
|
||||
if (ghostObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var renderers = ghostObject.Renderers;
|
||||
if (renderers == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var alpha = ghostObjectBehaviour.Alpha;
|
||||
|
||||
Debug.Log("Alpha Ghost:" + alpha);
|
||||
|
||||
if (!ghostObjectBehaviour.IgnoreGlobalAlpha)
|
||||
{
|
||||
alpha *= m_AlbertGhostMemoryCompositeSettings.Alpha;
|
||||
}
|
||||
|
||||
//
|
||||
// No need to render anything if the Alpha for this GhostObject is 0. Although the final composite will not
|
||||
// show anything we're wasting Draw calls drawing the Lit and Unlit(mask) versions of the Ghost Object Behaviours
|
||||
//
|
||||
if (alpha <= 0.0f) continue;
|
||||
|
||||
//
|
||||
// Let everything know we're rendering something this Ghost pass
|
||||
//
|
||||
++GhostObjectCollection.Instance.NumberOfObjectsRendered;
|
||||
|
||||
if (ghostObjectBehaviour.ReplacementMemoryMaterials != null)
|
||||
{
|
||||
DrawGhostRenderer(commandBuffer, renderers, alpha, useMemoryMaterial, ghostObjectBehaviour.ReplacementMemoryMaterials);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawGhostRenderer(commandBuffer, renderers, alpha, useMemoryMaterial);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGhostRenderer(CommandBuffer commandBuffer, Renderer[] renderers, float alpha,
|
||||
bool useMemoryMaterial, IReadOnlyList<Material> replacementMemoryMaterials = null)
|
||||
{
|
||||
|
||||
Debug.Log("Ghost Renderer " + renderers.Length);
|
||||
for (int j = 0, countj = renderers.Length; j < countj; ++j)
|
||||
{
|
||||
var renderer = renderers[j];
|
||||
if (renderer == null) continue;
|
||||
|
||||
m_MaterialPropertyBlock.SetFloat(k_PerGhostAlphaPropertyId, alpha);
|
||||
renderer.SetPropertyBlock(m_MaterialPropertyBlock);
|
||||
|
||||
m_SharedMaterials.Clear();
|
||||
renderer.GetSharedMaterials(m_SharedMaterials);
|
||||
if (m_SharedMaterials.Count > 0)
|
||||
{
|
||||
//for (int m = 0, countm = materials.Length; m < countm; ++m)
|
||||
for (int m = m_SharedMaterials.Count -1, countm = 0; m >= countm; --m)
|
||||
{
|
||||
if (useMemoryMaterial)
|
||||
{
|
||||
if (replacementMemoryMaterials != null && replacementMemoryMaterials.Count > 0 && replacementMemoryMaterials[m] != null)
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer,
|
||||
replacementMemoryMaterials[m], m,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer,
|
||||
m_MemoryMaterial, m,
|
||||
0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_SharedMaterials[m] == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!m_EditorLoggedNullMaterialRenderers.Contains(renderer))
|
||||
{
|
||||
Debug.LogErrorFormat(renderer, "AlbertGhostMemory: renderer {0} with null material",
|
||||
renderer.name);
|
||||
m_EditorLoggedNullMaterialRenderers.Add(renderer);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
commandBuffer.DrawRenderer(renderer,
|
||||
m_SharedMaterials[m], m,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (replacementMemoryMaterials != null && replacementMemoryMaterials.Count > 0 && replacementMemoryMaterials[0] != null)
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer,
|
||||
useMemoryMaterial ? replacementMemoryMaterials[0] : renderer.sharedMaterial);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer,
|
||||
useMemoryMaterial ? m_MemoryMaterial : renderer.sharedMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all GhostObjects using their default material/s
|
||||
/// </summary>
|
||||
private void DrawObjectsDefault(in CommandBuffer commandBuffer)
|
||||
{
|
||||
CoreUtils.SetRenderTarget(commandBuffer, m_MemoryRenderTexID, ClearFlag.All, Color.clear);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
DrawAllObjects(in commandBuffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all GhostObjects using the Ghost/Memory material
|
||||
/// </summary>
|
||||
private void DrawObjectsMemory(in CommandBuffer commandBuffer)
|
||||
{
|
||||
CoreUtils.SetRenderTarget(commandBuffer, m_MaskRenderTexID, ClearFlag.All, Color.clear);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
DrawAllObjects(in commandBuffer, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the Blur mask RT. This Blurs all the GhostObjects
|
||||
/// </summary>
|
||||
private void BlurMask(in CommandBuffer commandBuffer)
|
||||
{
|
||||
commandBuffer.Blit(m_MaskRenderTexID, m_BlurPassRenderTexID);
|
||||
|
||||
for (int i = 0; i < m_BlurPasses; ++i)
|
||||
{
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionX, 0);
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionY, 1);
|
||||
|
||||
commandBuffer.SetGlobalTexture(k_MainText, m_BlurPassRenderTexID);
|
||||
commandBuffer.Blit(m_BlurPassRenderTexID, m_TempRenderTexID,
|
||||
m_BlurMaterial, 0);
|
||||
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionX, 1);
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionY, 0);
|
||||
|
||||
commandBuffer.SetGlobalTexture(k_MainText, m_TempRenderTexID);
|
||||
commandBuffer.Blit(m_TempRenderTexID, m_BlurPassRenderTexID,
|
||||
m_BlurMaterial, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure Temporary RTs for XR
|
||||
/// Relies on ENABLE_VR
|
||||
/// </summary>
|
||||
/// <param name="cmd">SRF CommandBuffer</param>
|
||||
/// <returns>True if RTs were setup using XRSettings, Otherwise False.</returns>
|
||||
private bool ConfigureTemporaryRenderTexturesForXR(in CommandBuffer cmd)
|
||||
{
|
||||
#if ENABLE_VR
|
||||
if (!XRSettings.enabled) return false;
|
||||
var renderTextureDescriptor = XRSettings.eyeTextureDesc;
|
||||
cmd.GetTemporaryRT(m_MemoryRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_MaskRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
|
||||
renderTextureDescriptor.depthBufferBits = 0;
|
||||
renderTextureDescriptor.width = renderTextureDescriptor.height = m_BlurRes;
|
||||
|
||||
cmd.GetTemporaryRT(m_BlurPassRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_TempRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure Temporary RTs for SRF.
|
||||
/// </summary>
|
||||
/// <param name="cmd">SRF CommandBuffer</param>
|
||||
private void ConfigureTemporaryRenderTextures(in CommandBuffer cmd)
|
||||
{
|
||||
#if UNITY_SWITCH
|
||||
var width = 1280;
|
||||
var height = 720;
|
||||
#else
|
||||
var width = m_Camera.scaledPixelWidth;
|
||||
var height = m_Camera.scaledPixelHeight;
|
||||
#endif
|
||||
var aa = Mathf.Max(1, QualitySettings.antiAliasing);
|
||||
cmd.GetTemporaryRT(m_MemoryRenderTexID, width, height, 24, FilterMode.Bilinear, RenderTextureFormat.ARGB32,
|
||||
RenderTextureReadWrite.Default, aa);
|
||||
cmd.GetTemporaryRT(m_MaskRenderTexID, width >> 1, height >> 1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32,
|
||||
RenderTextureReadWrite.Default, aa);
|
||||
|
||||
cmd.GetTemporaryRT(m_BlurPassRenderTexID, m_BlurRes, m_BlurRes, 0, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_TempRenderTexID, m_BlurRes, m_BlurRes, 0, FilterMode.Bilinear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d65d0b4fad922724b96ef94f9d8b5b8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
[CreateAssetMenu(fileName = "New AlbertGhostMemorySettings",
|
||||
menuName = "Golems/Scriptable Render Features/AlbertGhostMemorySettings")]
|
||||
public class AlbertGhostMemorySettings : ScriptableObject
|
||||
{
|
||||
[SerializeField] private Vector3 m_LightDirection;
|
||||
|
||||
public Vector3 LightDirection
|
||||
{
|
||||
get => m_LightDirection;
|
||||
set => m_LightDirection = value;
|
||||
}
|
||||
|
||||
[SerializeField] private Color m_LightColour = Color.white;
|
||||
|
||||
public Color LightColour
|
||||
{
|
||||
get => m_LightColour;
|
||||
set => m_LightColour = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effects how far off centre each Blur sample becomes
|
||||
/// </summary>
|
||||
[Tooltip("Effects how far off centre each Blur sample becomes. Note, the bigger the number, the bigger the pixelation")]
|
||||
[Range(0.01f, 10.0f)][SerializeField] private float m_BlurRadius = .5f;
|
||||
public float BlurRadius => m_BlurRadius;
|
||||
|
||||
/// <summary>
|
||||
/// The number of Blur passes performed.
|
||||
/// This effects ALL objects rendered
|
||||
/// </summary>
|
||||
[Tooltip("How many times we Blur all the objects. Note, the bigger the number, the bigger the performance hit")]
|
||||
[Range(1, 10)][SerializeField] private int m_BlurPasses = 4;
|
||||
public int BlurPasses => m_BlurPasses;
|
||||
|
||||
/// <summary>
|
||||
/// Index into the m_BlurTextureSizes
|
||||
/// </summary>
|
||||
[Range(0,4)] [SerializeField] private int m_BlurTextureSize = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Texture size of the blur textures
|
||||
/// </summary>
|
||||
private int[] m_BlurTextureSizes = new int[5] { 128, 256, 512, 1024, 2048 };
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current Blur Texture resolution driven by m_BlurTextureSize
|
||||
/// </summary>
|
||||
public int BlurTextureResolution => m_BlurTextureSizes[
|
||||
Mathf.Max(0, Mathf.Min(m_BlurTextureSize, m_BlurTextureSizes.Length - 1))];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2ea357b0ff81244b8a3573234681896
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
/*
|
||||
using System;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
[Serializable]
|
||||
public class AlbertGhostMemorySettingsRef : AssetReferenceT<AlbertGhostMemorySettings>
|
||||
{
|
||||
public AlbertGhostMemorySettingsRef(string guid) : base(guid)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fe03499252946428c51d21897ebe3ce
|
||||
timeCreated: 1645029849
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
/*
|
||||
using RogueUtils.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class GhostMemoryLightDirection : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Light m_Light;
|
||||
[SerializeField] private Vector3 m_LightDirectionReference;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Debug.Assert(m_Light != null);
|
||||
Debug.Assert(m_LightDirectionReference != null);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
m_LightDirectionReference.variable.Value = (m_Light.transform.rotation * Vector3.forward).normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 085bb191568545a4eaafe27762a10deb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5786b509cdeae1043b4da27532f4b865
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using Golems.RenderFeatures;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class AlbertGhostMemoryComposite : SourceToDestinationBlitRenderFeature
|
||||
{
|
||||
[Header("Compose things")]
|
||||
[SerializeField] private bool m_IsEnabled = true;
|
||||
|
||||
[SerializeField] private AlbertGhostMemoryCompositeSettings m_FallbackSettings;
|
||||
private AlbertGhostMemoryCompositePass m_Pass;
|
||||
|
||||
private AlbertGhostMemoryCompositeSettings m_SettingsLoader;
|
||||
|
||||
[SerializeField]
|
||||
private float m_TimeBeforeSettingsFailureLog = 10.0f;
|
||||
|
||||
private float m_CreationTime;
|
||||
private bool m_LoggedSettingsFailure;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_LoggedSettingsFailure = false;
|
||||
m_CreationTime = Time.unscaledTime;
|
||||
bool logFallback = true;
|
||||
#if UNITY_EDITOR
|
||||
if (!EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
//
|
||||
// Cannot use Addressables in editor outside of playmode so use fallback
|
||||
//
|
||||
logFallback = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
m_SettingsLoader = m_FallbackSettings;
|
||||
|
||||
DoCreate();
|
||||
|
||||
m_Pass = new AlbertGhostMemoryCompositePass(m_SettingsLoader);
|
||||
|
||||
}
|
||||
private void DebugSetEnabledState(bool state)
|
||||
{
|
||||
m_IsEnabled = state;
|
||||
}
|
||||
private bool DebugGetEnabledState()
|
||||
{
|
||||
return m_IsEnabled;
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (m_Pass == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// If the source and destination are not the same then have to at least perform a copy.
|
||||
//
|
||||
var doRender = !IsSourceAndDestinationSame();
|
||||
|
||||
if (!doRender)
|
||||
{
|
||||
//
|
||||
// Source and destination are different so
|
||||
// see if there is something to render.
|
||||
//
|
||||
if (m_IsEnabled)
|
||||
{
|
||||
doRender = renderingData.cameraData.camera.isActiveAndEnabled &&
|
||||
GhostObjectCollection.Instance.NumberOfObjectsRendered > 0 &&
|
||||
GhostObjectCollection.Instance.HasSomethingToRender();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!doRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Pass.Setup(m_IsEnabled, m_WhenToInsert, renderer.cameraColorTarget,
|
||||
m_SourceTextureSourceType, m_SourceNamedTemporaryNameHash,
|
||||
m_DestinationTextureSourceType, m_DestinationNamedTemporaryNameHash,
|
||||
m_TempCopyNamedTemporaryNameHash);
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd24c7c60313ff546ba5e93072933a44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,167 @@
|
||||
using Golems.RenderFeatures;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR;
|
||||
using static Golems.ScriptableRenderPassHelper;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class AlbertGhostMemoryCompositePass : SourceToDestinationBlitRenderPass
|
||||
{
|
||||
private const string k_Shader = "Hidden/AlbertGhostMemoryComposite";
|
||||
private const string k_ProfilerIdent = "CompositePass";
|
||||
private AlbertGhostMemoryCompositeSettings m_Settings;
|
||||
private bool m_SettingsSet = false;
|
||||
private Material m_CompositeMat = null;
|
||||
private float m_Time = 0.0f;
|
||||
private bool m_IsEnabled;
|
||||
|
||||
#region Shader Properties
|
||||
private readonly int RandomValueID = Shader.PropertyToID("RandomValue");
|
||||
private readonly int TimeLapseID = Shader.PropertyToID("TimeLapse");
|
||||
private readonly int EdgeValueID = Shader.PropertyToID("EdgeValue");
|
||||
private readonly int GlobalAlphaID = Shader.PropertyToID("GlobalAlpha");
|
||||
private readonly int OffsetRedXID = Shader.PropertyToID("OffsetRedX");
|
||||
private readonly int OffsetGreenXID = Shader.PropertyToID("OffsetGreenX");
|
||||
private readonly int OffsetBlueXID = Shader.PropertyToID("OffsetBlueX");
|
||||
private readonly int OffsetRedYID = Shader.PropertyToID("OffsetRedY");
|
||||
private readonly int OffsetGreenYID = Shader.PropertyToID("OffsetGreenY");
|
||||
private readonly int OffsetBlueYID = Shader.PropertyToID("OffsetBlueY");
|
||||
private readonly int BrightnessID = Shader.PropertyToID("Brightness");
|
||||
private readonly int ContrastID = Shader.PropertyToID("Contrast");
|
||||
#endregion
|
||||
|
||||
public AlbertGhostMemoryCompositePass(AlbertGhostMemoryCompositeSettings settings)
|
||||
{
|
||||
SetSettings(settings);
|
||||
CreateMaterial(k_Shader, out m_CompositeMat);
|
||||
m_Time = 0.0f;
|
||||
}
|
||||
|
||||
public void SetSettings(AlbertGhostMemoryCompositeSettings settings)
|
||||
{
|
||||
m_Settings = settings;
|
||||
m_SettingsSet = m_Settings != null;
|
||||
}
|
||||
|
||||
public bool HasSettings()
|
||||
{
|
||||
return m_SettingsSet;
|
||||
}
|
||||
|
||||
public void Setup(bool isEnabled, RenderPassEvent whenToRender, RenderTargetIdentifier cameraColourTargetIdentifier,
|
||||
RenderFeatures.TextureSourceType sourceSourceType, int tempSourceTextureHash,
|
||||
RenderFeatures.TextureSourceType destinationSourceType, int tempDestinationTextureHash,
|
||||
int sameSourceDestTextureHash)
|
||||
{
|
||||
m_IsEnabled = isEnabled;
|
||||
DoSetup(whenToRender, cameraColourTargetIdentifier,
|
||||
sourceSourceType, tempSourceTextureHash,
|
||||
destinationSourceType, tempDestinationTextureHash,
|
||||
sameSourceDestTextureHash);
|
||||
}
|
||||
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
DoOnCameraSetup(cmd, ref renderingData);
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
if (!m_GoodToExecute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If we do not have settings yet we at least need to do a copy so later
|
||||
// stages have something to work with.
|
||||
//
|
||||
var forceCopy = !m_SettingsSet;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//
|
||||
// In Editor at edit time the material will get destroyed on scene load
|
||||
//
|
||||
if (m_CompositeMat == null)
|
||||
{
|
||||
CreateMaterial(k_Shader, out m_CompositeMat);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool doCopyOnly = forceCopy || !m_IsEnabled || GhostObjectCollection.Instance.NumberOfObjectsRendered <= 0;
|
||||
if (doCopyOnly)
|
||||
{
|
||||
//
|
||||
// nothing to render
|
||||
//
|
||||
if (!m_SourceAndDestinationSame)
|
||||
{
|
||||
//
|
||||
// Copy the source to the destination
|
||||
//
|
||||
var copyCmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
copyCmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
context.ExecuteCommandBuffer(copyCmd);
|
||||
CommandBufferPool.Release(copyCmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
SetAllShaderParameters();
|
||||
CommandBuffer cmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
|
||||
Compose(cmd);
|
||||
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup all the required values for
|
||||
/// the composition shader pass
|
||||
/// </summary>
|
||||
private void SetAllShaderParameters ()
|
||||
{
|
||||
m_Time += Time.deltaTime;
|
||||
|
||||
float random = Random.Range(0.0f, 1.0f);
|
||||
|
||||
m_CompositeMat.SetFloat(RandomValueID, random);
|
||||
m_CompositeMat.SetFloat(TimeLapseID, m_Time);
|
||||
m_CompositeMat.SetFloat(EdgeValueID, m_Settings.EdgeValue);
|
||||
m_CompositeMat.SetFloat(GlobalAlphaID, m_Settings.Alpha);
|
||||
|
||||
float ca_sin = m_Settings.ChromaticAberration * Mathf.Sin(m_Time * m_Settings.ChromaticAberrationSpeed);
|
||||
float ca_cos = m_Settings.ChromaticAberration * Mathf.Cos(m_Time * m_Settings.ChromaticAberrationSpeed);
|
||||
float ca_combo = (ca_sin + ca_cos);
|
||||
|
||||
m_CompositeMat.SetFloat(OffsetRedXID, ca_sin);
|
||||
m_CompositeMat.SetFloat(OffsetGreenXID, ca_combo);
|
||||
m_CompositeMat.SetFloat(OffsetBlueXID, ca_cos);
|
||||
m_CompositeMat.SetFloat(OffsetRedYID, ca_sin);
|
||||
m_CompositeMat.SetFloat(OffsetGreenYID, ca_combo);
|
||||
m_CompositeMat.SetFloat(OffsetBlueYID, -ca_cos);
|
||||
|
||||
m_CompositeMat.SetFloat(BrightnessID, m_Settings.Brightness);
|
||||
m_CompositeMat.SetFloat(ContrastID, m_Settings.Contrast);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compose the results of AlbertGhostMemoryPass into the cameraColorTarget
|
||||
/// </summary>
|
||||
private void Compose(in CommandBuffer cmd)
|
||||
{
|
||||
if (m_SourceAndDestinationSame)
|
||||
{
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_TempCopyTargetIdentifier, m_CompositeMat);
|
||||
cmd.Blit(m_TempCopyTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier, m_CompositeMat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8382ede0b6a95594ba9841fab6b21364
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
|
||||
[CreateAssetMenu(fileName = "New AlbertGhostMemoryCompositeSettings", menuName = "Golems/Scriptable Render Features/AlbertGhostMemoryCompositeSettings")]
|
||||
public class AlbertGhostMemoryCompositeSettings : ScriptableObject
|
||||
{
|
||||
[SerializeField] private float m_EdgeValue = 0.15f;
|
||||
public float EdgeValue
|
||||
{
|
||||
get => m_EdgeValue;
|
||||
set => m_EdgeValue = value;
|
||||
}
|
||||
|
||||
[SerializeField] private float m_ChromaticAberration = 0.0005f;
|
||||
public float ChromaticAberration
|
||||
{
|
||||
get => m_ChromaticAberration;
|
||||
set => m_ChromaticAberration = value;
|
||||
}
|
||||
|
||||
[SerializeField] private float m_ChromaticAberrationSpeed = 0.5f;
|
||||
public float ChromaticAberrationSpeed
|
||||
{
|
||||
get => m_ChromaticAberrationSpeed;
|
||||
set => m_ChromaticAberrationSpeed = value;
|
||||
}
|
||||
|
||||
[SerializeField] private float m_Brightness = 0.5f;
|
||||
public float Brightness
|
||||
{
|
||||
get => m_Brightness;
|
||||
set => m_Brightness = value;
|
||||
}
|
||||
|
||||
[SerializeField] private float m_Contrast = 1.0f;
|
||||
public float Contrast
|
||||
{
|
||||
get => m_Contrast;
|
||||
set => m_Contrast = value;
|
||||
}
|
||||
|
||||
[Range(0.0f, 1.0f)] public float m_Alpha = .5f;
|
||||
public float Alpha
|
||||
{
|
||||
get => m_Alpha;
|
||||
set => m_Alpha = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f4087f258649684b9620322674cf675
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
/*
|
||||
using System;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
[Serializable]
|
||||
public class AlbertGhostMemoryCompositeSettingsRef : AssetReferenceT<AlbertGhostMemoryCompositeSettings>
|
||||
{
|
||||
public AlbertGhostMemoryCompositeSettingsRef(string guid) : base(guid)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d87c60592bc40edbfcc3e1067ae34e5
|
||||
timeCreated: 1631024695
|
||||
@@ -0,0 +1,20 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2f4087f258649684b9620322674cf675, type: 3}
|
||||
m_Name: AlbertGhostMemoryCompositeSettings
|
||||
m_EditorClassIdentifier:
|
||||
m_EdgeValue: 0.045
|
||||
m_ChromaticAberration: 0.0005
|
||||
m_ChromaticAberrationSpeed: 0.5
|
||||
m_Brightness: 0.5
|
||||
m_Contrast: 1
|
||||
m_Alpha: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f90d567246daf5c44a47fbe69b9dc04c
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Scripts/RenderPasses/AlbertGhostMemorySettings.asset
Normal file
19
Assets/Scripts/RenderPasses/AlbertGhostMemorySettings.asset
Normal file
@@ -0,0 +1,19 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d2ea357b0ff81244b8a3573234681896, type: 3}
|
||||
m_Name: AlbertGhostMemorySettings
|
||||
m_EditorClassIdentifier:
|
||||
m_LightDirection: {x: -0.2, y: 1, z: -1}
|
||||
m_LightColour: {r: 0.8584906, g: 0.8584906, b: 0.8584906, a: 1}
|
||||
m_BlurRadius: 0.37
|
||||
m_BlurPasses: 4
|
||||
m_BlurTextureSize: 3
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 979479252af1bdb48b7e7929258a6da6
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
221
Assets/Scripts/RenderPasses/GhostObjectBehaviour.cs
Normal file
221
Assets/Scripts/RenderPasses/GhostObjectBehaviour.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
/// <summary>
|
||||
/// Ghost Object Behaviour sends all attached renderers via the AlbertGhostMemory effect
|
||||
/// NOTE:
|
||||
/// This is ExecuteInEditMode so that in the effect is visible in Editor at edit time. This
|
||||
/// helps Timeline authoring and similar as the alpha changes will be visible.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public class GhostObjectBehaviour : MonoBehaviour
|
||||
{
|
||||
private static SRDebuggerGhostAreRealSetting m_SRDebuggerGhostAreRealSettingInstance = null;
|
||||
|
||||
/// <summary>
|
||||
/// Global Alpha applied to all the renders attached
|
||||
/// to this behaviour. This is applied POST drawing
|
||||
/// everything so no clipping through meshes
|
||||
/// N.B Variable is serialized to allow setting it, but requires public controller to be set via animations
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Range(0f,1f)]
|
||||
private float m_Alpha = 1.0f;
|
||||
public float Alpha => m_Alpha;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to ignore the Global Alpha driven via the
|
||||
/// Alert Ghost Memory effect Settings. Will use m_Alpha if true
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private bool m_IgnoreGlobalAlpha = false;
|
||||
public bool IgnoreGlobalAlpha => m_IgnoreGlobalAlpha;
|
||||
|
||||
/// <summary>
|
||||
/// Really this should now just be m_Renderers..
|
||||
/// See docs for GhostObject
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private GhostObject m_GhostObject = new GhostObject();
|
||||
public GhostObject GhostObject => m_GhostObject;
|
||||
|
||||
[SerializeField]
|
||||
private List<Material> m_ReplacementMemoryMaterials;
|
||||
public List<Material> ReplacementMemoryMaterials => m_ReplacementMemoryMaterials;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
|
||||
GhostObjectCollection.Instance.AddGhostObjectBehaviour(this);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
if (m_SRDebuggerGhostAreRealSettingInstance == null)
|
||||
{
|
||||
m_SRDebuggerGhostAreRealSettingInstance = new SRDebuggerGhostAreRealSetting();
|
||||
}
|
||||
|
||||
if (m_SRDebuggerGhostAreRealSettingInstance != null)
|
||||
{
|
||||
m_SRDebuggerGhostAreRealSettingInstance.MakeGhostsGhosty += MakeGhostGhosty;
|
||||
m_SRDebuggerGhostAreRealSettingInstance.MakeGhostsReal += MakeGhostReal;
|
||||
|
||||
if (m_SRDebuggerGhostAreRealSettingInstance.GetGhostsGhosty())
|
||||
{
|
||||
MakeGhostGhosty();
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeGhostReal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (m_SRDebuggerGhostAreRealSettingInstance != null)
|
||||
{
|
||||
m_SRDebuggerGhostAreRealSettingInstance.MakeGhostsGhosty -= MakeGhostGhosty;
|
||||
m_SRDebuggerGhostAreRealSettingInstance.MakeGhostsReal -= MakeGhostReal;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
|
||||
GhostObjectCollection.Instance.RemoveGhostObjectBehaviour(this);
|
||||
}
|
||||
|
||||
private void MakeGhostGhosty()
|
||||
{
|
||||
if (m_GhostObject != null)
|
||||
{
|
||||
foreach (var renderer in m_GhostObject.Renderers)
|
||||
{
|
||||
renderer.gameObject.layer = LayerMask.NameToLayer("Default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeGhostReal()
|
||||
{
|
||||
if (m_GhostObject != null)
|
||||
{
|
||||
foreach (var renderer in m_GhostObject.Renderers)
|
||||
{
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.gameObject.layer = LayerMask.NameToLayer("Ghost");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the local Alpha of the
|
||||
/// Ghost Object Behaviour to the passed value
|
||||
/// </summary>
|
||||
/// <param name="alpha"></param>
|
||||
public void SetAlpha(float alpha)
|
||||
{
|
||||
if (alpha <= 1 && alpha >= 0 )
|
||||
{
|
||||
m_Alpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void GrabAllRenderers()
|
||||
{
|
||||
var renderList = new List<Renderer>();
|
||||
foreach(var rend in GetComponentsInChildren<Renderer>())
|
||||
{
|
||||
if (rend as ParticleSystemRenderer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rend as TrailRenderer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rend as LineRenderer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
renderList.Add(rend);
|
||||
}
|
||||
|
||||
if (renderList.Count > 0)
|
||||
{
|
||||
m_GhostObject.SetRenderers(renderList.ToArray());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class SRDebuggerGhostAreRealSetting
|
||||
{
|
||||
public UnityAction MakeGhostsReal;
|
||||
public UnityAction MakeGhostsGhosty;
|
||||
private bool m_IsGhosty = false;
|
||||
|
||||
|
||||
public bool GetGhostsGhosty()
|
||||
{
|
||||
return m_IsGhosty;
|
||||
}
|
||||
|
||||
public void SetGhostsGhosty(bool shouldBeGhosty)
|
||||
{
|
||||
if (shouldBeGhosty != m_IsGhosty)
|
||||
{
|
||||
if (shouldBeGhosty)
|
||||
{
|
||||
Debug.Log("make em Ghosty");
|
||||
MakeGhostsGhosty?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("make em Real");
|
||||
MakeGhostsReal?.Invoke();
|
||||
}
|
||||
m_IsGhosty = shouldBeGhosty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ghost Object is somewhat deprecated. However it remains as the Renderers in the scene
|
||||
/// are all hooked up to the instance of GhostObject via GhostObjectBehaviour.
|
||||
/// N.B We use to only pass around GhostObject but features got more demanding
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class GhostObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Renderers to be drawn through Albert Ghost Memory Pass
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Renderer[] m_Renderers;
|
||||
|
||||
public Renderer[] Renderers => m_Renderers;
|
||||
|
||||
public void SetRenderers(Renderer[] renderers)
|
||||
{
|
||||
m_Renderers = renderers;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
11
Assets/Scripts/RenderPasses/GhostObjectBehaviour.cs.meta
Normal file
11
Assets/Scripts/RenderPasses/GhostObjectBehaviour.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfbaee30bb007114a800edbac3d011fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
73
Assets/Scripts/RenderPasses/GhostObjectCollection.cs
Normal file
73
Assets/Scripts/RenderPasses/GhostObjectCollection.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
/// <summary>
|
||||
/// A gross singleton collection of all the Ghost Object Behaviours
|
||||
/// which require rendering via Albert Ghost Memory This is purely
|
||||
/// convenience for the AlbertGhostMemory to access Ghost Object Behaviours
|
||||
/// and for Ghost Object Behaviours to register/unregister themselves.
|
||||
/// </summary>
|
||||
public class GhostObjectCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// The active singleton of GhostObjectCollection
|
||||
/// </summary>
|
||||
private static GhostObjectCollection m_Instance;
|
||||
|
||||
public static GhostObjectCollection Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Instance == null) new GhostObjectCollection();
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collection of all the Ghost Object Behaviours which require rendering
|
||||
/// </summary>
|
||||
public List<GhostObjectBehaviour> GhostObjectBehaviours { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flag if there's anything Ghost Object Behaviours which require rendering
|
||||
/// </summary>
|
||||
public bool HasSomethingToRender()=> GhostObjectBehaviours != null && GhostObjectBehaviours.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// The number of objects rendered in AlbertGhostMemoryPass.
|
||||
/// This is reset in AlbertGhostMemoryPass.Execute() and incremented in
|
||||
/// DrawObjectsDefault().
|
||||
/// ComposeOutlinePass uses this in AddRenderPasses, if it's zero screen copy Blit is avoided.
|
||||
///
|
||||
/// N.B This is a sketchy place to do this sort of thing, full acknowledged but it's quick, easy and works...
|
||||
/// </summary>
|
||||
public int NumberOfObjectsRendered = 0;
|
||||
|
||||
private GhostObjectCollection()
|
||||
{
|
||||
m_Instance = this;
|
||||
GhostObjectBehaviours = new List<GhostObjectBehaviour>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the passed Ghost Object Behaviour to Albert Ghost Memory pass
|
||||
/// </summary>
|
||||
public void AddGhostObjectBehaviour(GhostObjectBehaviour ghostObjectBehaviour)
|
||||
{
|
||||
if (ghostObjectBehaviour == null) return;
|
||||
GhostObjectBehaviours.Add(ghostObjectBehaviour);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the passed Ghost Object Behaviour to Albert Ghost Memory pass
|
||||
/// </summary>
|
||||
public void RemoveGhostObjectBehaviour(GhostObjectBehaviour ghostObjectBehaviour)
|
||||
{
|
||||
if (ghostObjectBehaviour == null) return;
|
||||
GhostObjectBehaviours.Remove(ghostObjectBehaviour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/RenderPasses/GhostObjectCollection.cs.meta
Normal file
11
Assets/Scripts/RenderPasses/GhostObjectCollection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f90bf4d03ebb874fadb90762d16cdac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/RenderPasses/Outline.meta
Normal file
8
Assets/Scripts/RenderPasses/Outline.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a278621c72f85e546baf1ba6f79f6ffe
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,140 @@
|
||||
using Golems.RenderFeatures;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class ComposeOutlineScriptableRenderFeature : SourceToDestinationBlitRenderFeature
|
||||
{
|
||||
|
||||
|
||||
[SerializeField] private bool m_IsEnabled = true;
|
||||
|
||||
[Header("Compose things")]
|
||||
[SerializeField] private Material m_CompositeMaterial = default;
|
||||
|
||||
private ComposeOutlinePass m_Pass;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_Pass = new ComposeOutlinePass(m_CompositeMaterial);
|
||||
|
||||
DoCreate();
|
||||
|
||||
}
|
||||
|
||||
private void DebugSetEnabledState(bool state)
|
||||
{
|
||||
m_IsEnabled = state;
|
||||
}
|
||||
private bool DebugGetEnabledState()
|
||||
{
|
||||
return m_IsEnabled;
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (IsSourceAndDestinationSame())
|
||||
{
|
||||
//
|
||||
// The source and destination are same can skip the pass if there is
|
||||
// nothing to render.
|
||||
//
|
||||
var outlineObjects = OutlineCollection.RendererBundles;
|
||||
if (outlineObjects == null || outlineObjects.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_Pass.Setup(m_IsEnabled,m_WhenToInsert, renderer.cameraColorTarget,
|
||||
m_SourceTextureSourceType, m_SourceNamedTemporaryNameHash,
|
||||
m_DestinationTextureSourceType, m_DestinationNamedTemporaryNameHash,
|
||||
m_TempCopyNamedTemporaryNameHash);
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
}
|
||||
}
|
||||
|
||||
public class ComposeOutlinePass : SourceToDestinationBlitRenderPass
|
||||
{
|
||||
private const string k_ProfilerIdent = "ComposeOutlinePass";
|
||||
|
||||
private Material m_CompositeMat = null;
|
||||
|
||||
private bool m_IsEnabled;
|
||||
|
||||
private readonly int m_BlurTexId = Shader.PropertyToID("_BlurTex");
|
||||
private readonly int m_DefaultDrawObjectsTexId = Shader.PropertyToID("_DefaultDrawObjects");
|
||||
|
||||
public ComposeOutlinePass(Material compositeMaterial)
|
||||
{
|
||||
m_CompositeMat = compositeMaterial;
|
||||
}
|
||||
|
||||
public void Setup(bool isEnabled, RenderPassEvent whenToRender, RenderTargetIdentifier cameraColourTargetIdentifier,
|
||||
RenderFeatures.TextureSourceType sourceSourceType, int tempSourceTextureHash,
|
||||
RenderFeatures.TextureSourceType destinationSourceType, int tempDestinationTextureHash,
|
||||
int sameSourceDestTextureHash)
|
||||
{
|
||||
m_IsEnabled = isEnabled;
|
||||
|
||||
DoSetup(whenToRender, cameraColourTargetIdentifier,
|
||||
sourceSourceType, tempSourceTextureHash,
|
||||
destinationSourceType, tempDestinationTextureHash,
|
||||
sameSourceDestTextureHash);
|
||||
}
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
DoOnCameraSetup(cmd, ref renderingData);
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
//
|
||||
// The OutlineCollection.NumberOfObjectsRendered is set during the
|
||||
// OutlineScriptableRenderPass.Execute() so if that did not render anything then there is
|
||||
// nothing to compose.
|
||||
//
|
||||
if (!m_GoodToExecute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool doCopyOnly = (OutlineCollection.NumberOfObjectsRendered <= 0) || !m_IsEnabled;
|
||||
if (doCopyOnly)
|
||||
{
|
||||
if (!m_SourceAndDestinationSame)
|
||||
{
|
||||
//
|
||||
// Copy the source to the destination
|
||||
//
|
||||
var copyCmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
copyCmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
context.ExecuteCommandBuffer(copyCmd);
|
||||
CommandBufferPool.Release(copyCmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var cmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
|
||||
cmd.SetGlobalTexture("_BlurTex", m_BlurTexId);
|
||||
cmd.SetGlobalTexture("_DefaultDrawObjects", m_DefaultDrawObjectsTexId);
|
||||
|
||||
if (m_SourceAndDestinationSame)
|
||||
{
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_TempCopyTargetIdentifier, m_CompositeMat);
|
||||
cmd.Blit(m_TempCopyTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier, m_CompositeMat);
|
||||
}
|
||||
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96781a865a3cc54488e7e18c2b1d66bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/RenderPasses/Outline/Materials.meta
Normal file
8
Assets/Scripts/RenderPasses/Outline/Materials.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce653e0167dc8c94e8ae26729b6e04a5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,127 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: CompositeMaterial
|
||||
m_Shader: {fileID: 4800000, guid: 5f0ea674bfa1ff042b2829daa5815e90, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EdgeTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _AlphaClip: 0
|
||||
- _Blend: 0
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
--- !u!114 &5329936352101645292
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
version: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 495a07472af496441a0c4612a21198c0
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
125
Assets/Scripts/RenderPasses/Outline/Materials/DepthOnly.mat
Normal file
125
Assets/Scripts/RenderPasses/Outline/Materials/DepthOnly.mat
Normal file
@@ -0,0 +1,125 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: DepthOnly
|
||||
m_Shader: {fileID: 4800000, guid: 59ed4cb0e31a72c469f09fcf8614de92, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AlphaClip: 0
|
||||
- _Blend: 0
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
--- !u!114 &1157606769240496216
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
version: 5
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79176156d5c314b43acbee3df46cfeb1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,123 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: SolidUnlitMaterial
|
||||
m_Shader: {fileID: 4800000, guid: e249b16da4133f84e91d3718a2719884, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _AlphaClip: 0
|
||||
- _Blend: 0
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _Cutoff: 0.5
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
--- !u!114 &7988618175867360684
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
version: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7df10f98bf57cb43a96870442b5ed13
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
348
Assets/Scripts/RenderPasses/Outline/Outline2.cs
Normal file
348
Assets/Scripts/RenderPasses/Outline/Outline2.cs
Normal file
@@ -0,0 +1,348 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Golems.Attributes;
|
||||
using RogueUtils.Data;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Golems;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
//This was used over outline entity due to it already being on the objects
|
||||
public partial class Outline2 : MonoBehaviour
|
||||
{
|
||||
|
||||
[Header("HighEndOutlineSettingsBelow ==================")]
|
||||
/// <summary>
|
||||
/// Renderer's attached to this GameObject
|
||||
/// </summary>
|
||||
///
|
||||
[OnValueChanged("UpdateRendererBundle")]
|
||||
[SerializeField]
|
||||
private Renderer[] m_Renderers;
|
||||
|
||||
public Renderer[] Renderers
|
||||
{
|
||||
get => m_Renderers;
|
||||
set => m_Renderers = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outline Colour
|
||||
/// </summary>
|
||||
[FormerlySerializedAs("outlineColor")]
|
||||
[SerializeField]
|
||||
private Color m_OutlineColor = Color.white;
|
||||
|
||||
[Header("The color variable will override local color if it exists")]
|
||||
public ColorVariable OutlineColorVariable;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10)]
|
||||
private float m_BlurRadius = 2.5f;
|
||||
|
||||
public float BlurRadius
|
||||
{
|
||||
get => m_BlurRadius;
|
||||
set => m_BlurRadius = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 1)]
|
||||
private float m_Alpha = 1;
|
||||
|
||||
public float Alpha
|
||||
{
|
||||
get => m_Alpha;
|
||||
set => m_Alpha = value;
|
||||
}
|
||||
|
||||
[SerializeField] private float m_FadeSpeed = 7.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Returns True if Outline is currently active (m_Alpha >=1).
|
||||
/// Otherwise, returns False.
|
||||
/// </summary>
|
||||
public bool IsOutlining => m_Alpha >= 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The current active Fade Coroutine
|
||||
/// </summary>
|
||||
private Coroutine m_FadeCoroutine = default;
|
||||
|
||||
/// <summary>
|
||||
/// WaitForSeconds used before Fade in/out begins
|
||||
/// </summary>
|
||||
private WaitForSeconds m_FadeDelay = new WaitForSeconds(.1f);
|
||||
|
||||
[Header("OutlineTypeToggle ==================")]
|
||||
[SerializeField]
|
||||
private bool m_UseLowEndOutline = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
#if UNITY_SWITCH
|
||||
m_UseLowEndOutline = true;
|
||||
#endif
|
||||
//if (GolemsGameManager.IsPlayerXR())
|
||||
if (false)
|
||||
{
|
||||
m_UseLowEndOutline = true;
|
||||
}
|
||||
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HighEndAwake();
|
||||
}
|
||||
}
|
||||
|
||||
private void HighEndAwake()
|
||||
{
|
||||
if (m_Renderers.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No renderers setup for outline in editor on " + gameObject.name +
|
||||
". Grabbing them through code");
|
||||
|
||||
var renderers = new List<Renderer>();
|
||||
|
||||
//
|
||||
// Check OutlineEntity for Renderer
|
||||
//
|
||||
if (TryGetComponent<Renderer>(out var r))
|
||||
{
|
||||
renderers.Add(r);
|
||||
}
|
||||
|
||||
SetRenderers(renderers);
|
||||
}
|
||||
|
||||
OutlineCollection.AddRenderer(this);
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HighEndOnEnable();
|
||||
}
|
||||
}
|
||||
|
||||
private void HighEndOnEnable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Debug.Log("Disabling Outline");
|
||||
Alpha = 0;
|
||||
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HighEndOnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void HighEndOnDestroy()
|
||||
{
|
||||
|
||||
OutlineCollection.RemoveRenderer(this);
|
||||
Alpha = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void ToggleOutlining()
|
||||
{
|
||||
if (m_Alpha > 0)
|
||||
{
|
||||
StopOutlining();
|
||||
}
|
||||
else
|
||||
{
|
||||
StartOutlining();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates/Deactivates the Outline,
|
||||
/// depending on the given true or false value.
|
||||
/// </summary>
|
||||
/// <param name="active"> Activate or deactivate the Outline,
|
||||
/// where true activates the Outline and false deactivates the Outline.</param>
|
||||
public void SetOutlineActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
StartOutlining();
|
||||
}
|
||||
else
|
||||
{
|
||||
StopOutlining();
|
||||
}
|
||||
}
|
||||
|
||||
[Button]
|
||||
public void StartOutlining()
|
||||
{
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
Debug.Log("Start Outlining");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StartHighEndOutlining();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartHighEndOutlining()
|
||||
{
|
||||
//Debug.Log("StartOutlining");
|
||||
if (m_FadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(m_FadeCoroutine);
|
||||
m_FadeCoroutine = null;
|
||||
}
|
||||
|
||||
//
|
||||
// protect against running on disabled game objects
|
||||
//
|
||||
if (gameObject.activeInHierarchy)
|
||||
{
|
||||
m_FadeCoroutine = StartCoroutine(Fade(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Button]
|
||||
public void StopOutlining()
|
||||
{
|
||||
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
Debug.Log("Stop Outlining");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StopHighEndOutlining();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopHighEndOutlining()
|
||||
{
|
||||
|
||||
if (m_FadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(m_FadeCoroutine);
|
||||
m_FadeCoroutine = null;
|
||||
}
|
||||
|
||||
//
|
||||
// protect against running on disabled game objects
|
||||
//
|
||||
if (gameObject.activeInHierarchy)
|
||||
{
|
||||
m_FadeCoroutine = StartCoroutine(Fade(-1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private IEnumerator Fade(int dir)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
bool faded = false;
|
||||
while (!faded)
|
||||
{
|
||||
var alpha = Alpha;
|
||||
alpha += (dir * m_FadeSpeed) * Time.deltaTime;
|
||||
alpha = Mathf.Clamp01(alpha);
|
||||
Alpha = alpha;
|
||||
faded = dir < 0 ? alpha <= 0.0f : alpha >= 1.0f;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
m_FadeCoroutine = null;
|
||||
}
|
||||
[ContextMenu("Force Stop Outlining")]
|
||||
/// <summary>
|
||||
/// Forces alpha to 0 to avoid showing if moved immediately
|
||||
/// </summary>
|
||||
public void ForceStopOutlining()
|
||||
{
|
||||
if (m_UseLowEndOutline)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRenderers(List<Renderer> renderers)
|
||||
{
|
||||
m_Renderers = renderers.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current Color for this Outline instance.
|
||||
/// If the Outline has a OutlineColorVariable the value
|
||||
/// of the passed Color variable will be set to the scriptable
|
||||
/// variable value. Otherwise, it will be set to this Outlines m_OutlineColor.
|
||||
/// </summary>
|
||||
/// <param name="colour">Color variable to store this instances current outline colour</param>
|
||||
public void GetColour(out Color colour)
|
||||
{
|
||||
colour = OutlineColorVariable == null ? m_OutlineColor : OutlineColorVariable.Value;
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/RenderPasses/Outline/Outline2.cs.meta
Normal file
11
Assets/Scripts/RenderPasses/Outline/Outline2.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05d346d0dd4384f4fad966bd1340ddd5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
43
Assets/Scripts/RenderPasses/Outline/OutlineCollection.cs
Normal file
43
Assets/Scripts/RenderPasses/Outline/OutlineCollection.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public static class OutlineCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection of renderers to be drawn with outline process
|
||||
/// </summary>
|
||||
public readonly static List<Outline2> RendererBundles = new List<Outline2>();
|
||||
|
||||
/// <summary>
|
||||
/// The number of objects rendered in OutlineScriptableRenderPass.
|
||||
/// This is reset in OutlineScriptableRenderPass.Execute() and incremented in
|
||||
/// DrawObjectsDefault().
|
||||
/// ComposeOutlinePass uses this in AddRenderPasses, if it's zero screen copy Blit is avoided.
|
||||
///
|
||||
/// N.B This is a sketchy place to do this sort of thing, full acknowledged but it's quick, easy and works...
|
||||
/// </summary>
|
||||
public static int NumberOfObjectsRendered = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds collection of renderers to the Outline Collection
|
||||
/// </summary>
|
||||
/// <param name="rendererBundle">Renderers to be drawn with Outline process</param>
|
||||
public static void AddRenderer(Outline2 rendererBundle)
|
||||
{
|
||||
if (RendererBundles.Contains(rendererBundle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RendererBundles.Add(rendererBundle);
|
||||
}
|
||||
|
||||
public static void RemoveRenderer(Outline2 rendererBundle)
|
||||
{
|
||||
RendererBundles.Remove(rendererBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff2eba45467bff142ac34388a8cfe9b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,453 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
#if ENABLE_VR
|
||||
using UnityEngine.XR;
|
||||
#endif
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class OutlineScriptableRenderFeature : ScriptableRendererFeature
|
||||
{
|
||||
|
||||
[SerializeField] private bool m_IsEnabled = true;
|
||||
|
||||
[SerializeField]
|
||||
private Material m_SolidUnlitMaterial = default;
|
||||
|
||||
[SerializeField]
|
||||
private Material m_BlurMaterial = default;
|
||||
|
||||
private OutlineScriptableRenderPass m_Pass = default;
|
||||
|
||||
[SerializeField] private RenderPassEvent m_RenderPassEvent = RenderPassEvent.AfterRenderingOpaques;
|
||||
|
||||
/// <summary>
|
||||
/// The number of Blur passes performed.
|
||||
/// This effects ALL objects rendered
|
||||
/// </summary>
|
||||
[Tooltip("How many times we Blur all the objects. Note, the bigger the number, the bigger the performance hit")]
|
||||
[Range(1, 10)][SerializeField] private int m_BlurPasses = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Effects how far off centre each Blur sample becomes
|
||||
/// </summary>
|
||||
[Tooltip("Effects how far off centre each Blur sample becomes. Note, the bigger the number, the bigger the pixelation")]
|
||||
[Range(0.0f, 10.0f)] [SerializeField] private float m_BlurRadius = .5f;
|
||||
|
||||
/// <summary>
|
||||
/// Index into the m_BlurTextureSizes
|
||||
/// </summary>
|
||||
[Range(0,4)] [SerializeField] private int m_BlurTextureSize = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Texture size of the blur textures
|
||||
/// </summary>
|
||||
private int[] m_BlurTextureSizes = new int[5] { 128, 256, 512, 1024, 2048 };
|
||||
|
||||
[Header("Outlines Occluders")]
|
||||
/// <summary>
|
||||
/// Material used to render the occluders
|
||||
/// </summary>
|
||||
[Tooltip("Material used to render the occluders")]
|
||||
[SerializeField] Material m_OutlinesOccludersMat;
|
||||
|
||||
/// <summary>
|
||||
/// Used to set the objects that will be part of the outlines occluders
|
||||
/// </summary>
|
||||
[Tooltip("Used to set the objects that will be part of the outlines occluders")]
|
||||
[SerializeField] LayerMask m_OccludersMask;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this feature's resources.
|
||||
/// </summary>
|
||||
public override void Create()
|
||||
{
|
||||
m_Pass = new OutlineScriptableRenderPass(m_SolidUnlitMaterial, m_BlurMaterial, m_OutlinesOccludersMat, m_OccludersMask);
|
||||
|
||||
}
|
||||
|
||||
private void DebugSetEnabledState(bool state)
|
||||
{
|
||||
m_IsEnabled = state;
|
||||
}
|
||||
private bool DebugGetEnabledState()
|
||||
{
|
||||
return m_IsEnabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Injects the outline ScriptableRenderPass into the renderer.
|
||||
/// </summary>
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (!m_IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Zeroing this here in case the pass is not added
|
||||
//
|
||||
OutlineCollection.NumberOfObjectsRendered = 0;
|
||||
var outlineRenderers = OutlineCollection.RendererBundles;
|
||||
if (outlineRenderers == null || outlineRenderers.Count <= 0) return;
|
||||
|
||||
m_Pass.Setup(
|
||||
m_RenderPassEvent,
|
||||
renderingData.cameraData.camera,
|
||||
outlineRenderers,
|
||||
m_BlurPasses,
|
||||
m_BlurRadius,
|
||||
m_BlurTextureSizes[Mathf.Max(0, Mathf.Min(m_BlurTextureSize, m_BlurTextureSizes.Length-1))]);
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
}
|
||||
}
|
||||
|
||||
public class OutlineScriptableRenderPass : ScriptableRenderPass
|
||||
{
|
||||
private const string k_ProfilerIdent = "Outline";
|
||||
|
||||
#region Texture Consts
|
||||
private const string k_DefaultDrawObjectsTex = "_DefaultDrawObjects";
|
||||
private const string k_SolidDrawObjectsTex = "_SolidDrawObjects";
|
||||
private const string k_BlurTex = "_BlurTex";
|
||||
private const string k_MainText = "_MainTex";
|
||||
private const string k_TempTex = "_TempTex";
|
||||
#endregion Texture Consts
|
||||
|
||||
#region Shader Fields
|
||||
private readonly int m_ColourID = Shader.PropertyToID("_Color");
|
||||
private readonly int m_AlphaID = Shader.PropertyToID("_Alpha");
|
||||
|
||||
private readonly int m_BlurResolution = Shader.PropertyToID("_BlurResolution");
|
||||
private readonly int m_BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
private readonly int m_BlurDirectionX = Shader.PropertyToID("_BlurDirectionX");
|
||||
private readonly int m_BlurDirectionY = Shader.PropertyToID("_BlurDirectionY");
|
||||
#endregion Shader Fields
|
||||
|
||||
#region Render Texture IDs
|
||||
private readonly int m_DefaultDrawObjects = Shader.PropertyToID(k_DefaultDrawObjectsTex);
|
||||
private readonly int m_SolidDrawObjects = Shader.PropertyToID(k_SolidDrawObjectsTex);
|
||||
private readonly int m_BlurPassRenderTexID = Shader.PropertyToID(k_BlurTex);
|
||||
private readonly int m_TempRenderTexID = Shader.PropertyToID(k_TempTex);
|
||||
#endregion
|
||||
|
||||
private Camera m_Camera;
|
||||
private IList<Outline2> m_Renderers;
|
||||
private Material m_SolidUnlitMaterial;
|
||||
private Material m_BlurMaterial;
|
||||
|
||||
/// <summary>
|
||||
/// The uniform Blur texture size, calculated from the current screen size
|
||||
/// </summary>
|
||||
private int m_BlurRes;
|
||||
|
||||
/// <summary>
|
||||
/// Effects how far off centre each Blur sample becomes
|
||||
/// </summary>
|
||||
private float m_BlurRad = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The number of Blur passes performed.
|
||||
/// This effects ALL objects rendered
|
||||
/// </summary>
|
||||
private int m_BlurPasses = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Used in DrawObjectsXYZ. We use this in conjunction with GetSharedMaterials.
|
||||
/// Avoids GC alloc from .sharedMaterials
|
||||
/// </summary>
|
||||
private readonly List<Material> m_SharedMaterials = new List<Material>();
|
||||
|
||||
/// <summary>
|
||||
/// Used to Get and Store the each Outline instances Color
|
||||
/// </summary>
|
||||
private Color m_OutlineColour = new Color(1,1,1,1);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Occluders shader tags list
|
||||
/// </summary>
|
||||
private List<ShaderTagId> m_ShaderTagsList = new List<ShaderTagId>();
|
||||
|
||||
/// <summary>
|
||||
/// Filter settings for occluders rendering
|
||||
/// </summary>
|
||||
private FilteringSettings m_FilteringSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Material used to render the occluders
|
||||
/// </summary>
|
||||
private Material m_OccludersOverrideMaterial;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private readonly HashSet<Outline2> m_EditorLoggedNullMaterialOutlines = new HashSet<Outline2>();
|
||||
private readonly HashSet<Renderer> m_EditorLoggedNullMaterialRenderers = new HashSet<Renderer>();
|
||||
#endif
|
||||
|
||||
public OutlineScriptableRenderPass(Material solidUnlitMaterial, Material blurMaterial, Material occludersOverrideMaterial, LayerMask occludersMask)
|
||||
{
|
||||
m_BlurMaterial = blurMaterial;
|
||||
m_SolidUnlitMaterial = solidUnlitMaterial;
|
||||
m_OccludersOverrideMaterial = occludersOverrideMaterial;
|
||||
|
||||
// Initialise occluders related properties
|
||||
m_ShaderTagsList.Add(new ShaderTagId("SRPDefaultUnlit"));
|
||||
m_ShaderTagsList.Add(new ShaderTagId("UniversalForward"));
|
||||
m_ShaderTagsList.Add(new ShaderTagId("UniversalForwardOnly"));
|
||||
m_ShaderTagsList.Add(new ShaderTagId("ForwardLit"));
|
||||
|
||||
m_FilteringSettings = new FilteringSettings(RenderQueueRange.opaque, occludersMask);
|
||||
}
|
||||
|
||||
public void Setup(RenderPassEvent whenToRender, Camera camera, IList<Outline2> renderers, int blurPasses,
|
||||
float blurRadius, int blurTextureSize)
|
||||
{
|
||||
renderPassEvent = whenToRender;
|
||||
m_Renderers = renderers;
|
||||
m_Camera = camera;
|
||||
m_BlurPasses = blurPasses;
|
||||
m_BlurRad = blurRadius;
|
||||
m_BlurRes = blurTextureSize;
|
||||
}
|
||||
|
||||
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
||||
{
|
||||
//
|
||||
// Attempt to make RTs for XR, otherwise use Default Settings
|
||||
//
|
||||
if (!ConfigureTemporaryRenderTexturesForXR(in cmd)) ConfigureTemporaryRenderTextures(in cmd);
|
||||
}
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
ConfigureTarget(m_SolidDrawObjects);
|
||||
ConfigureClear(ClearFlag.All, Color.clear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the pass. This is where custom rendering occurs. Specific details are left to the implementation
|
||||
/// </summary>
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
//
|
||||
// Always make sure we reset, this is the begining of a new Outline process
|
||||
//
|
||||
OutlineCollection.NumberOfObjectsRendered = 0;
|
||||
|
||||
var cmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
cmd.Clear();
|
||||
|
||||
//
|
||||
// First render objects using their default materials
|
||||
//
|
||||
DrawObjectsDefault(cmd);
|
||||
|
||||
//
|
||||
// OutlineCollection.NumberOfObjectsRendered is incremented
|
||||
// inside DrawObjectsDefault. If it's 0 we rendered nothing.
|
||||
//
|
||||
if (OutlineCollection.NumberOfObjectsRendered > 0)
|
||||
{
|
||||
DrawOccluders(context, ref renderingData);
|
||||
DrawObjectsSolid(cmd);
|
||||
cmd.SetGlobalFloat(m_BlurResolution, m_BlurRes);
|
||||
cmd.SetGlobalFloat(m_BlurRadius, m_BlurRad);
|
||||
DrawBlur(in cmd);
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
}
|
||||
|
||||
cmd.Clear();
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw outlines occluders
|
||||
/// </summary>
|
||||
private void DrawOccluders(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
// Draw the occluders into m_SolidDrawObjects
|
||||
// This pass will fill in the depth buffer so that the outlines could get occluded by the soldiers or other occluders as needed
|
||||
DrawingSettings drawingSettings = CreateDrawingSettings(m_ShaderTagsList, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
|
||||
|
||||
drawingSettings.overrideMaterial = m_OccludersOverrideMaterial;
|
||||
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all objects using their default material/s
|
||||
/// </summary>
|
||||
private void DrawObjectsDefault(in CommandBuffer commandBuffer)
|
||||
{
|
||||
CoreUtils.SetRenderTarget(commandBuffer, m_DefaultDrawObjects, ClearFlag.All, Color.clear);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
for (int i = 0, counti = m_Renderers.Count; i < counti; ++i)
|
||||
{
|
||||
var outline = m_Renderers[i];
|
||||
|
||||
//
|
||||
// Don't waste time drawing objects which are currently invisible
|
||||
//
|
||||
if (outline.Alpha <= 0) continue;
|
||||
|
||||
++OutlineCollection.NumberOfObjectsRendered;
|
||||
|
||||
var outlineRenderers = outline.Renderers;
|
||||
for (int j = 0; j < outlineRenderers.Length; j++)
|
||||
{
|
||||
var renderer = outlineRenderers[j];
|
||||
if (renderer == null) continue;
|
||||
m_SharedMaterials.Clear();
|
||||
renderer.GetSharedMaterials(m_SharedMaterials);
|
||||
|
||||
if (m_SharedMaterials.Count > 0)
|
||||
{
|
||||
for (int m = 0, countm = m_SharedMaterials.Count; m < countm; ++m)
|
||||
{
|
||||
if (m_SharedMaterials[m] == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!m_EditorLoggedNullMaterialOutlines.Contains(outline))
|
||||
{
|
||||
Debug.LogErrorFormat(outline, "Outline {0} has a renderer {1} with null material", outline.name, renderer.name);
|
||||
m_EditorLoggedNullMaterialOutlines.Add(outline);
|
||||
}
|
||||
if (!m_EditorLoggedNullMaterialRenderers.Contains(renderer))
|
||||
{
|
||||
Debug.LogErrorFormat(outline, "Outline {0} has a renderer {1} with null material", outline.name, renderer.name);
|
||||
m_EditorLoggedNullMaterialRenderers.Add(renderer);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
commandBuffer.DrawRenderer(renderer, m_SharedMaterials[m], m, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer, renderer.material);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw all objects using the special Solid Unlit shader
|
||||
/// </summary>
|
||||
private void DrawObjectsSolid(in CommandBuffer commandBuffer)
|
||||
{
|
||||
CoreUtils.SetRenderTarget(commandBuffer, m_SolidDrawObjects, ClearFlag.None, Color.clear);
|
||||
//commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
for (int i = 0, counti = m_Renderers.Count; i < counti; ++i)
|
||||
{
|
||||
var outline = m_Renderers[i];
|
||||
if (outline.Alpha <= 0) continue;
|
||||
|
||||
outline.GetColour(out m_OutlineColour);
|
||||
commandBuffer.SetGlobalColor(m_ColourID, m_OutlineColour);
|
||||
commandBuffer.SetGlobalFloat(m_AlphaID, outline.Alpha);
|
||||
|
||||
var outlineRenderers = outline.Renderers;
|
||||
for (int j = 0; j < outlineRenderers.Length; ++j)
|
||||
{
|
||||
var renderer = outlineRenderers[j];
|
||||
if (renderer == null) continue;
|
||||
m_SharedMaterials.Clear();
|
||||
renderer.GetSharedMaterials(m_SharedMaterials);
|
||||
|
||||
if (m_SharedMaterials.Count > 0)
|
||||
{
|
||||
for (int m = 0, countm = m_SharedMaterials.Count; m < countm; ++m)
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer, m_SolidUnlitMaterial, m, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBuffer.DrawRenderer(renderer, m_SolidUnlitMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the Blur mask RT. Blur the Outline objects
|
||||
/// </summary>
|
||||
private void DrawBlur(in CommandBuffer commandBuffer)
|
||||
{
|
||||
commandBuffer.Blit(m_SolidDrawObjects, m_BlurPassRenderTexID);
|
||||
|
||||
for (int i = 0, counti = m_BlurPasses; i < counti; ++i)
|
||||
{
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionX, 0);
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionY, 1);
|
||||
|
||||
commandBuffer.SetGlobalTexture(k_MainText, m_BlurPassRenderTexID);
|
||||
commandBuffer.Blit(m_BlurPassRenderTexID, m_TempRenderTexID,
|
||||
m_BlurMaterial, 0);
|
||||
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionX, 1);
|
||||
commandBuffer.SetGlobalFloat(m_BlurDirectionY, 0);
|
||||
|
||||
commandBuffer.SetGlobalTexture(k_MainText, m_TempRenderTexID);
|
||||
commandBuffer.Blit(m_TempRenderTexID, m_BlurPassRenderTexID,
|
||||
m_BlurMaterial, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure Temporary RTs for XR
|
||||
/// Relies on ENABLE_VR
|
||||
/// </summary>
|
||||
/// <param name="cmd">SRF CommandBuffer</param>
|
||||
/// <returns>True if RTs were setup using XRSettings, Otherwise False.</returns>
|
||||
private bool ConfigureTemporaryRenderTexturesForXR(in CommandBuffer cmd)
|
||||
{
|
||||
#if ENABLE_VR
|
||||
if (!XRSettings.enabled) return false;
|
||||
var renderTextureDescriptor = XRSettings.eyeTextureDesc;
|
||||
cmd.GetTemporaryRT(m_DefaultDrawObjects, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_SolidDrawObjects, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
|
||||
renderTextureDescriptor.depthBufferBits = 0;
|
||||
|
||||
renderTextureDescriptor.width = renderTextureDescriptor.height = m_BlurRes;
|
||||
|
||||
cmd.GetTemporaryRT(m_BlurPassRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_TempRenderTexID, renderTextureDescriptor, FilterMode.Bilinear);
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure Temporary RTs for SRF.
|
||||
/// </summary>
|
||||
/// <param name="cmd">SRF CommandBuffer</param>
|
||||
private void ConfigureTemporaryRenderTextures(in CommandBuffer cmd)
|
||||
{
|
||||
var width = m_Camera.scaledPixelWidth;
|
||||
var height = m_Camera.scaledPixelHeight;
|
||||
|
||||
var aa = Mathf.Max(1, QualitySettings.antiAliasing);
|
||||
|
||||
//
|
||||
// We can't really down sample the Solid Render. This is the render of the
|
||||
//
|
||||
cmd.GetTemporaryRT(m_DefaultDrawObjects, width, height, 24, FilterMode.Bilinear,
|
||||
RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default, aa);
|
||||
|
||||
cmd.GetTemporaryRT(m_SolidDrawObjects, width >> 1, height >> 1, 24,
|
||||
FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default,aa);
|
||||
|
||||
cmd.GetTemporaryRT(m_BlurPassRenderTexID, m_BlurRes, m_BlurRes, 0, FilterMode.Bilinear);
|
||||
cmd.GetTemporaryRT(m_TempRenderTexID, m_BlurRes, m_BlurRes, 0, FilterMode.Bilinear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8114b26188dce7043a962383e5b26228
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/RenderPasses/Outline/Shaders.meta
Normal file
8
Assets/Scripts/RenderPasses/Outline/Shaders.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0e655ad25360a540b63cad86a6c256d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
95
Assets/Scripts/RenderPasses/Outline/Shaders/Blur.shader
Normal file
95
Assets/Scripts/RenderPasses/Outline/Shaders/Blur.shader
Normal file
@@ -0,0 +1,95 @@
|
||||
Shader "Outline/Blur"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Texture", 2D) = "white" {}
|
||||
}
|
||||
//https://github.com/mattdesl/lwjgl-basics/blob/master/test/mdesl/test/shadertut/ShaderLesson5.java
|
||||
SubShader
|
||||
{
|
||||
Cull Off ZWrite Off ZTest Always
|
||||
|
||||
// Combined
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex);
|
||||
half4 _MainTex_ST;
|
||||
|
||||
uniform float _BlurResolution;
|
||||
uniform float _BlurRadius;
|
||||
uniform float _BlurDirectionX;
|
||||
uniform float _BlurDirectionY;
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_OUTPUT(v2f, o);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
{
|
||||
//_BlurRadius = 2.5f;
|
||||
//our original texcoord for this fragment
|
||||
fixed2 tc = UnityStereoScreenSpaceUVAdjust(i.uv, _MainTex_ST);
|
||||
|
||||
//float r = lerp(_BlurResolution.y, _BlurResolution.x, step(_BlurDirection.x, 1.0f));
|
||||
|
||||
//the amount to blur, i.e. how far off center to sample from
|
||||
//1.0 -> blur by one pixel
|
||||
//2.0 -> blur by two pixels, etc.
|
||||
float blur = _BlurRadius/_BlurResolution;
|
||||
|
||||
//the _BlurDirectionection of our blur
|
||||
//(1.0, 0.0) -> x-axis blur
|
||||
//(0.0, 1.0) -> y-axis blur
|
||||
float hstep = _BlurDirectionX;
|
||||
float vstep = _BlurDirectionY;
|
||||
|
||||
//apply blurring, using a 9-tap filter with predefined gaussian weights
|
||||
|
||||
fixed4 sum = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0162162162;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.0540540541;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.1216216216;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.1945945946;
|
||||
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x, tc.y)) * 0.2270270270;
|
||||
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.1945945946;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.1216216216;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.0540540541;
|
||||
sum += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, fixed2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.0162162162;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Assets/Scripts/RenderPasses/Outline/Shaders/Blur.shader.meta
Normal file
10
Assets/Scripts/RenderPasses/Outline/Shaders/Blur.shader.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f88f058dc01de7343af2ff63b364efd1
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Scripts/RenderPasses/Outline/Shaders/Compose.shader
Normal file
106
Assets/Scripts/RenderPasses/Outline/Shaders/Compose.shader
Normal file
@@ -0,0 +1,106 @@
|
||||
Shader "Outline/Compose"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Texture", any) = "white" {}
|
||||
_EdgeTex ("Edge 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;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 uv0 : TEXCOORD0;
|
||||
float2 uv1 : TEXCOORD1;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
float2 _MainTex_TexelSize;
|
||||
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex);
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_DefaultDrawObjects);
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_BlurTex);
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_TempTex);
|
||||
UNITY_DECLARE_SCREENSPACE_TEXTURE(_EdgeTex);
|
||||
|
||||
uniform float EdgeValue;
|
||||
|
||||
uniform float OffsetRedX;
|
||||
uniform float OffsetGreenX;
|
||||
uniform float OffsetBlueX;
|
||||
uniform float OffsetRedY;
|
||||
uniform float OffsetGreenY;
|
||||
uniform float OffsetBlueY;
|
||||
|
||||
uniform float Brightness;
|
||||
uniform float Contrast;
|
||||
|
||||
uniform float GlobalAlpha;
|
||||
|
||||
half4 _MainTex_ST;
|
||||
half4 _EdgeTex_ST;
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_OUTPUT(v2f, o);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv0 = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
o.uv1 = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
if (_MainTex_TexelSize.y < 0)
|
||||
o.uv1.y = 1 - o.uv1.y;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
{
|
||||
EdgeValue = 1.0f;
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
||||
//
|
||||
// Sample the world RT (render so far without our outline objects)
|
||||
//
|
||||
fixed4 world = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex,
|
||||
UnityStereoScreenSpaceUVAdjust(i.uv0, _MainTex_ST));
|
||||
//
|
||||
// Sample our outline texture
|
||||
//
|
||||
fixed4 outline = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_BlurTex,
|
||||
UnityStereoScreenSpaceUVAdjust(i.uv1, _MainTex_ST));
|
||||
//
|
||||
// Sample the solid render of the game object to be outlined
|
||||
//
|
||||
fixed4 gameObject = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_DefaultDrawObjects,
|
||||
UnityStereoScreenSpaceUVAdjust(i.uv1, _MainTex_ST));
|
||||
|
||||
world.xyz = world + EdgeValue * (outline * (1.0 - gameObject.a));
|
||||
return world;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27d8ba6291e352149af60962aa391bf9
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
41
Assets/Scripts/RenderPasses/Outline/Shaders/DepthOnly.shader
Normal file
41
Assets/Scripts/RenderPasses/Outline/Shaders/DepthOnly.shader
Normal file
@@ -0,0 +1,41 @@
|
||||
Shader "Outline/DepthOnly"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType"="Opaque" }
|
||||
LOD 100
|
||||
ColorMask 0
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
};
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
{
|
||||
return fixed4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6b291dfa48d17347b6a1a85acb509c0
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
Shader "Outline/SolidUnlit"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType" = "TransparentCutout" }
|
||||
ZWrite Off
|
||||
ZTest LEqual
|
||||
Lighting Off
|
||||
// Set up alpha blending
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float4 projPos : TEXCOORD0;
|
||||
float2 convertedNormal : TEXCOORD1;
|
||||
};
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
|
||||
o.projPos = ComputeScreenPos(o.vertex);
|
||||
COMPUTE_EYEDEPTH(o.projPos.z);
|
||||
|
||||
//o.viewNormal = COMPUTE_VIEW_NORMAL;
|
||||
|
||||
// work out camera position to vert position
|
||||
float3 normalDir = UnityObjectToWorldNormal(v.normal);
|
||||
float3 viewDir = normalize(WorldSpaceViewDir(v.vertex));
|
||||
|
||||
float3 upDir = float3(0.0, 1.0, 0.0);
|
||||
float3 rightDir = normalize(cross(viewDir, upDir));
|
||||
upDir = cross(rightDir, viewDir);
|
||||
|
||||
o.convertedNormal.x = dot(rightDir, normalDir);
|
||||
o.convertedNormal.y = dot(upDir, normalDir);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 _Color;
|
||||
float _Alpha;
|
||||
|
||||
fixed4 frag(v2f i) : COLOR0
|
||||
{
|
||||
fixed4 output = _Color;
|
||||
|
||||
output.a = output.a * _Alpha;
|
||||
|
||||
clip((output.a - 0));
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7aa60114ab92b94cbe33203434b8fa7
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
176
Assets/Scripts/RenderPasses/ScreenFadeFeature.cs
Normal file
176
Assets/Scripts/RenderPasses/ScreenFadeFeature.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using Golems.RenderFeatures;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using Golems.Attributes;
|
||||
using RogueUtils.Data;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using static Golems.ScriptableRenderPassHelper;
|
||||
|
||||
namespace Golems
|
||||
{
|
||||
public class ScreenFadeFeature : SourceToDestinationBlitRenderFeature
|
||||
{
|
||||
[Header("Screen fade things")]
|
||||
//
|
||||
// This is the fade colour used to fade the screen.
|
||||
// It is up to whatever is setting this to correctly set the alpha.
|
||||
//
|
||||
[SerializeField]
|
||||
private ColorVariable m_TargetFadeColour = default;
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_IsEnabled;;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_IsEnabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_IsEnabled = false;
|
||||
|
||||
|
||||
private ScreenFadePass m_Pass = default;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_Pass = new ScreenFadePass(m_TargetFadeColour);
|
||||
|
||||
DoCreate();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void DebugSetEnabledState(bool state)
|
||||
{
|
||||
m_IsEnabled = state;
|
||||
}
|
||||
private bool DebugGetEnabledState()
|
||||
{
|
||||
return m_IsEnabled;
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (IsSourceAndDestinationSame() && !m_IsEnabled)
|
||||
{
|
||||
//
|
||||
// Can skip this pass as the source and destination are the same and the fade
|
||||
// is not enabled.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
m_Pass.Setup(m_IsEnabled, m_WhenToInsert, renderer.cameraColorTarget,
|
||||
m_SourceTextureSourceType, m_SourceNamedTemporaryNameHash,
|
||||
m_DestinationTextureSourceType, m_DestinationNamedTemporaryNameHash,
|
||||
m_TempCopyNamedTemporaryNameHash);
|
||||
renderer.EnqueuePass(m_Pass);
|
||||
}
|
||||
}
|
||||
|
||||
public class ScreenFadePass : SourceToDestinationBlitRenderPass
|
||||
{
|
||||
private const string k_ProfilerIdent = "ScreenFadePass";
|
||||
private const string k_ScreenFaderCompositeShader = "Hidden/ScreenFaderComposite";
|
||||
private const string k_FadeColour = "_FadeColour";
|
||||
|
||||
private static readonly int k_FadeColourId = Shader.PropertyToID(k_FadeColour);
|
||||
|
||||
private Material m_ScreenFaderCompositeMaterial = default;
|
||||
|
||||
private readonly Color m_FadeColour;
|
||||
|
||||
private bool m_IsEnabled;
|
||||
|
||||
public ScreenFadePass(ColorVariable colourVariable)
|
||||
{
|
||||
CreateMaterial(k_ScreenFaderCompositeShader, out m_ScreenFaderCompositeMaterial);
|
||||
m_FadeColour = Color.white;
|
||||
}
|
||||
|
||||
public void Setup(bool isEnabled, RenderPassEvent whenToRender, RenderTargetIdentifier cameraColourTargetIdentifier,
|
||||
RenderFeatures.TextureSourceType sourceSourceType, int tempSourceTextureHash,
|
||||
RenderFeatures.TextureSourceType destinationSourceType, int tempDestinationTextureHash,
|
||||
int sameSourceDestTextureHash)
|
||||
{
|
||||
m_IsEnabled = isEnabled;
|
||||
DoSetup(whenToRender, cameraColourTargetIdentifier,
|
||||
sourceSourceType, tempSourceTextureHash,
|
||||
destinationSourceType, tempDestinationTextureHash,
|
||||
sameSourceDestTextureHash);
|
||||
}
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
DoOnCameraSetup(cmd, ref renderingData);
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (m_ScreenFaderCompositeMaterial == null)
|
||||
{
|
||||
//
|
||||
// In Editor the material will get destroyed on scene change
|
||||
//
|
||||
CreateMaterial(k_ScreenFaderCompositeShader, out m_ScreenFaderCompositeMaterial);
|
||||
if (m_ScreenFaderCompositeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!m_GoodToExecute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set up all the shader parameters here!
|
||||
//
|
||||
var fadeColour = m_FadeColour;
|
||||
|
||||
bool doCopyOnly = fadeColour.a == 0.0f || !m_IsEnabled;
|
||||
if (doCopyOnly)
|
||||
{
|
||||
//
|
||||
// Nothing to blend
|
||||
//
|
||||
if (!m_SourceAndDestinationSame)
|
||||
{
|
||||
//
|
||||
// Copy the source to the destination
|
||||
//
|
||||
var copyCmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
copyCmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
context.ExecuteCommandBuffer(copyCmd);
|
||||
CommandBufferPool.Release(copyCmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_ScreenFaderCompositeMaterial.SetColor(k_FadeColourId, fadeColour);
|
||||
|
||||
var cmd = CommandBufferPool.Get(k_ProfilerIdent);
|
||||
|
||||
if (m_SourceAndDestinationSame)
|
||||
{
|
||||
// Blit the Camera into the screen copy texture using the the fader shader
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_TempCopyTargetIdentifier, m_ScreenFaderCompositeMaterial);
|
||||
// blit back into the camera texture
|
||||
cmd.Blit(m_TempCopyTargetIdentifier, m_DestinationTargetIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.Blit(m_SourceTargetIdentifier, m_DestinationTargetIdentifier, m_ScreenFaderCompositeMaterial);
|
||||
}
|
||||
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/RenderPasses/ScreenFadeFeature.cs.meta
Normal file
11
Assets/Scripts/RenderPasses/ScreenFadeFeature.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cfbbb311db9e36408a12b505ac48f16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,323 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace Golems.RenderFeatures
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for RenderFeatures that take a source and do some operation on it and put
|
||||
/// the result into some destination.
|
||||
/// This base class provides settings for the source and destination textures via
|
||||
/// RenderFeatures.TextureSourceType, allowing the named temporary texture name to be given
|
||||
/// if need (named textures are provided by TemporaryCameraCopyTextureRenderFeature).
|
||||
/// Can also set a named textures as a temporary copy texture if the source and destination
|
||||
/// are the same.
|
||||
/// </summary>
|
||||
public abstract class SourceToDestinationBlitRenderFeature : ScriptableRendererFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The texture source type of the source of the pass.
|
||||
/// Camera colour or named temporary texture.
|
||||
/// </summary>
|
||||
[Header("Source and Destination")]
|
||||
[SerializeField]
|
||||
protected RenderFeatures.TextureSourceType m_SourceTextureSourceType = RenderFeatures.TextureSourceType.CameraColour;
|
||||
|
||||
/// <summary>
|
||||
/// If the source is a named texture then this is its name.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_SourceNamedTemporaryName;
|
||||
|
||||
protected int m_SourceNamedTemporaryNameHash;
|
||||
|
||||
/// <summary>
|
||||
/// The texture source type of the destination of the pass.
|
||||
/// Camera colour or named temporary texture.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
protected RenderFeatures.TextureSourceType m_DestinationTextureSourceType = RenderFeatures.TextureSourceType.CameraColour;
|
||||
|
||||
/// <summary>
|
||||
/// If the destination is a named texture then this is its name.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_DestinationNamedTemporaryName;
|
||||
|
||||
protected int m_DestinationNamedTemporaryNameHash;
|
||||
|
||||
/// <summary>
|
||||
/// If the source and destination are the same then this named texture can be used as
|
||||
/// the temporary copy location.
|
||||
/// If not set then a the pass will create its own temporary texture.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_TempCopyNamedTemporaryName;
|
||||
|
||||
protected int m_TempCopyNamedTemporaryNameHash;
|
||||
|
||||
/// <summary>
|
||||
/// When to insert the pass
|
||||
/// </summary>
|
||||
[Header("What stage")]
|
||||
[SerializeField]
|
||||
protected RenderPassEvent m_WhenToInsert = RenderPassEvent.BeforeRenderingPostProcessing;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hashes of the named texture names.
|
||||
///
|
||||
/// NOTE: this should be called in the Create() of sub-classes.
|
||||
/// </summary>
|
||||
protected void DoCreate()
|
||||
{
|
||||
SetTextureNameHashes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the source and destination are the same.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected bool IsSourceAndDestinationSame()
|
||||
{
|
||||
if (m_SourceTextureSourceType == TextureSourceType.CameraColour &&
|
||||
m_DestinationTextureSourceType == TextureSourceType.CameraColour)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_SourceTextureSourceType == TextureSourceType.NameTemporary &&
|
||||
m_DestinationTextureSourceType == TextureSourceType.NameTemporary)
|
||||
{
|
||||
//
|
||||
// Both using a named temporary texture, are they the same
|
||||
//
|
||||
return m_SourceNamedTemporaryNameHash == m_DestinationNamedTemporaryNameHash;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the texture name hashes from the current name values.
|
||||
/// </summary>
|
||||
protected void SetTextureNameHashes()
|
||||
{
|
||||
m_SourceNamedTemporaryNameHash =
|
||||
TemporaryCameraCopyTextureRenderFeature.GetNameHash(m_SourceNamedTemporaryName);
|
||||
m_DestinationNamedTemporaryNameHash =
|
||||
TemporaryCameraCopyTextureRenderFeature.GetNameHash(m_DestinationNamedTemporaryName);
|
||||
m_TempCopyNamedTemporaryNameHash =
|
||||
TemporaryCameraCopyTextureRenderFeature.GetNameHash(m_TempCopyNamedTemporaryName);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private bool m_EditorTextureHashesFoldout;
|
||||
protected virtual void EditorOnInspectorGUIAfterBase()
|
||||
{
|
||||
EditorGUILayout.LabelField("Info", EditorStyles.boldLabel);
|
||||
|
||||
var origIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel += 1;
|
||||
m_EditorTextureHashesFoldout = EditorGUILayout.Foldout(m_EditorTextureHashesFoldout, "Texture hashes");
|
||||
if (m_EditorTextureHashesFoldout)
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
|
||||
EditorGUI.indentLevel += 1;
|
||||
EditorTextureNameAndHash("Source", m_SourceNamedTemporaryName, m_SourceNamedTemporaryNameHash);
|
||||
|
||||
EditorTextureNameAndHash("Destination", m_DestinationNamedTemporaryName,
|
||||
m_DestinationNamedTemporaryNameHash);
|
||||
|
||||
EditorTextureNameAndHash("Source", m_SourceNamedTemporaryName, m_SourceNamedTemporaryNameHash);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel = origIndent;
|
||||
|
||||
EditorGUILayout.LabelField("Controls", EditorStyles.boldLabel);
|
||||
|
||||
//
|
||||
// NOTE:
|
||||
// This button is not actually needed as the Create() of the render feature is called
|
||||
// if the exposed settings are changed.
|
||||
//
|
||||
if (GUILayout.Button("Update temp texture hashes"))
|
||||
{
|
||||
SetTextureNameHashes();
|
||||
}
|
||||
}
|
||||
|
||||
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(SourceToDestinationBlitRenderFeature), true)]
|
||||
private class SourceToDestinationBlitRenderFeatureEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
var me = target as SourceToDestinationBlitRenderFeature;
|
||||
if (me != null)
|
||||
{
|
||||
me.EditorOnInspectorGUIAfterBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The RenderPass for things that take a source, do some operation on it and put the
|
||||
/// result in some destination.
|
||||
///
|
||||
/// NOTE:
|
||||
/// If the source and destination are different then the execute must at least copy the
|
||||
/// source to the destination (as long as m_GoodToExecute is true) otherwise later
|
||||
/// passes may not see the correct texture contents.
|
||||
/// </summary>
|
||||
public abstract class SourceToDestinationBlitRenderPass : ScriptableRenderPass
|
||||
{
|
||||
/// <summary>
|
||||
/// If this pass needs to create a temporary texture (when the source and destination
|
||||
/// are the same) then is id is used.
|
||||
/// </summary>
|
||||
protected readonly int m_ScreenCopyID = Shader.PropertyToID("_ScreenCopy");
|
||||
|
||||
protected RenderFeatures.TextureSourceType m_SourceTextureSourceType;
|
||||
protected int m_SourceNamedTemporaryNameHash;
|
||||
|
||||
protected RenderFeatures.TextureSourceType m_DestinationTextureSourceType;
|
||||
protected int m_DestinationNamedTemporaryNameHash;
|
||||
|
||||
protected int m_SameSourceDestNamedTemporaryNameHash;
|
||||
|
||||
protected bool m_SourceAndDestinationSame;
|
||||
|
||||
/// <summary>
|
||||
/// If this is true then Execute() can happen, if false something went wrong in the pass setup
|
||||
/// so the Execute() should do nothing.
|
||||
/// </summary>
|
||||
protected bool m_GoodToExecute;
|
||||
|
||||
protected RenderTargetIdentifier m_CameraColourTargetIdentifier;
|
||||
protected RenderTargetIdentifier m_SourceTargetIdentifier;
|
||||
protected RenderTargetIdentifier m_DestinationTargetIdentifier;
|
||||
protected RenderTargetIdentifier m_TempCopyTargetIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the named textures and/or the camera colour texture and determines if the
|
||||
/// source and destination are the same.
|
||||
///
|
||||
/// NOTE:
|
||||
/// Call this from whatever setup type method the sub-class implements.
|
||||
/// </summary>
|
||||
protected void DoSetup(RenderPassEvent whenToRender, RenderTargetIdentifier cameraColourTargetIdentifier,
|
||||
RenderFeatures.TextureSourceType sourceSourceType, int tempSourceTextureHash,
|
||||
RenderFeatures.TextureSourceType destinationSourceType, int tempDestinationTextureHash,
|
||||
int sameSourceDestTextureHash)
|
||||
{
|
||||
renderPassEvent = whenToRender;
|
||||
m_CameraColourTargetIdentifier = cameraColourTargetIdentifier;
|
||||
|
||||
m_SourceTextureSourceType = sourceSourceType;
|
||||
m_SourceNamedTemporaryNameHash = tempSourceTextureHash;
|
||||
|
||||
m_DestinationTextureSourceType = destinationSourceType;
|
||||
m_DestinationNamedTemporaryNameHash = tempDestinationTextureHash;
|
||||
|
||||
m_SameSourceDestNamedTemporaryNameHash = sameSourceDestTextureHash;
|
||||
|
||||
m_SourceAndDestinationSame = false;
|
||||
|
||||
if (m_SourceTextureSourceType == TextureSourceType.CameraColour &&
|
||||
m_DestinationTextureSourceType == TextureSourceType.CameraColour)
|
||||
{
|
||||
m_SourceAndDestinationSame = true;
|
||||
}
|
||||
else if (m_SourceTextureSourceType == TextureSourceType.NameTemporary &&
|
||||
m_DestinationTextureSourceType == TextureSourceType.NameTemporary)
|
||||
{
|
||||
//
|
||||
// Both using a named temporary texture, are they the same
|
||||
//
|
||||
m_SourceAndDestinationSame = (m_SourceNamedTemporaryNameHash == m_DestinationNamedTemporaryNameHash);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the named textures and works out if all textures are available meaning that
|
||||
/// execution of the pass can go ahead.
|
||||
/// This create the local temporary copy texture if that is required.
|
||||
/// This sets up the RenderTargetIdentifiers the Execute() can then use.
|
||||
/// </summary>
|
||||
protected void DoOnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
m_GoodToExecute = false;
|
||||
if (m_SourceTextureSourceType == TextureSourceType.CameraColour)
|
||||
{
|
||||
m_SourceTargetIdentifier = m_CameraColourTargetIdentifier;
|
||||
}
|
||||
else if (!TemporaryCameraCopyTextureRenderFeature.TryGetTempTextureIdentifier(m_SourceNamedTemporaryNameHash, out m_SourceTargetIdentifier))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_DestinationTextureSourceType == TextureSourceType.CameraColour)
|
||||
{
|
||||
m_DestinationTargetIdentifier = m_CameraColourTargetIdentifier;
|
||||
}
|
||||
else if (!TemporaryCameraCopyTextureRenderFeature.TryGetTempTextureIdentifier(m_DestinationNamedTemporaryNameHash, out m_DestinationTargetIdentifier))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_SourceAndDestinationSame)
|
||||
{
|
||||
//
|
||||
// need some texture to use as a copy
|
||||
//
|
||||
if (m_SameSourceDestNamedTemporaryNameHash != TemporaryCameraCopyTextureRenderFeature.k_InvalidNameHash)
|
||||
{
|
||||
if (!TemporaryCameraCopyTextureRenderFeature.TryGetTempTextureIdentifier(m_SameSourceDestNamedTemporaryNameHash, out m_TempCopyTargetIdentifier))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Use our own temporary texture
|
||||
//
|
||||
#if ENABLE_VR
|
||||
var renderTextureDescriptor = XRSettings.enabled ? XRSettings.eyeTextureDesc : renderingData.cameraData.cameraTargetDescriptor;
|
||||
#else
|
||||
var renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
|
||||
#endif
|
||||
cmd.GetTemporaryRT(m_ScreenCopyID, renderTextureDescriptor);
|
||||
m_TempCopyTargetIdentifier = new RenderTargetIdentifier(m_ScreenCopyID);
|
||||
}
|
||||
}
|
||||
|
||||
m_GoodToExecute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40029c1675b242128cce0aca3279af9e
|
||||
timeCreated: 1645724187
|
||||
3
Assets/Scripts/RenderPasses/TemporaryCameraTexture.meta
Normal file
3
Assets/Scripts/RenderPasses/TemporaryCameraTexture.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b806ceb5145941258d9c69f267bcdd00
|
||||
timeCreated: 1645691203
|
||||
@@ -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
|
||||
20
Assets/Scripts/RenderPasses/TextureSourceType.cs
Normal file
20
Assets/Scripts/RenderPasses/TextureSourceType.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Golems.RenderFeatures
|
||||
{
|
||||
/// <summary>
|
||||
/// The source of a texture used in a RenderFeature.
|
||||
/// NOTE:
|
||||
/// These are serialised, DO NOT renumber or reorder as that will break what enum a serialised
|
||||
/// value translates to.
|
||||
/// </summary>
|
||||
public enum TextureSourceType
|
||||
{
|
||||
/// <summary>
|
||||
/// The Camera's colour texture.
|
||||
/// </summary>
|
||||
CameraColour,
|
||||
/// <summary>
|
||||
/// A named temporary texture from TemporaryCameraCopyTextureRenderFeature
|
||||
/// </summary>
|
||||
NameTemporary,
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/RenderPasses/TextureSourceType.cs.meta
Normal file
3
Assets/Scripts/RenderPasses/TextureSourceType.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0891c03b558945158d3d2819cdf26c4c
|
||||
timeCreated: 1645718086
|
||||
Reference in New Issue
Block a user