BITFALL/Assets/Plugins/_MK/MKGlow/Scripts/PipelineExtensions.cs

206 lines
8.2 KiB
C#

//////////////////////////////////////////////////////
// MK Glow Extensions //
// //
// Created by Michael Kremmel //
// www.michaelkremmel.de //
// Copyright © 2021 All rights reserved. //
//////////////////////////////////////////////////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace MK.Glow
{
using ShaderProperties = PipelineProperties.ShaderProperties;
internal static class PipelineExtensions
{
private static Mesh _screenMesh;
private static Mesh screenMesh
{
get
{
if(_screenMesh == null)
{
_screenMesh = new Mesh { name = "MKGlowScreenMesh" };
_screenMesh.SetVertices(new List<Vector3>
{
new Vector3(-1f, -1f, 0f),
new Vector3( 3f, -1f, 0f),
new Vector3(-1f, 3f, 0f)
});
_screenMesh.SetIndices(new[] { 0, 1, 2 }, MeshTopology.Triangles, 0, false);
_screenMesh.UploadMeshData(false);
}
return _screenMesh;
}
}
public static void Destroy(UnityEngine.Object obj)
{
if (obj != null)
{
#if UNITY_EDITOR
if (Application.isPlaying)
UnityEngine.Object.Destroy(obj);
else
UnityEngine.Object.DestroyImmediate(obj);
#else
UnityEngine.Object.Destroy(obj);
#endif
}
}
/// <summary>
/// Enable or disable a specific Shader keyword
/// </summary>
/// <param name="cmd"></param>
/// <param name="keyword"></param>
/// <param name="enable"></param>
internal static void SetKeyword(this CommandBuffer cmd, string keyword, bool enable)
{
if(enable)
cmd.EnableShaderKeyword(keyword);
else
cmd.DisableShaderKeyword(keyword);
}
internal static void SetKeyword(string keyword, bool enable)
{
if(enable)
Shader.EnableKeyword(keyword);
else
Shader.DisableKeyword(keyword);
}
/// <summary>
/// Draw the currently setuped render context with its targets
/// </summary>
/// <param name="cmd"></param>
/// <param name="destinations"></param>
/// <param name="material"></param>
/// <param name="useGeometryShader"></param>
/// <param name="pass"></param>
internal static void Draw(this CommandBuffer cmd, List<RenderTarget> destinations, Material material, bool useGeometryShader, int pass, Rect viewport)
{
cmd.SetRenderTargetContext(destinations);
cmd.SetViewport(viewport);
if(useGeometryShader)
{
cmd.DrawProcedural(Matrix4x4.identity, material, pass, MeshTopology.Points, 1);
}
else
{
cmd.DrawMesh(screenMesh, Matrix4x4.identity, material, 0, pass);
}
}
internal static void Draw(List<RenderTarget> destinations, Material material, bool useGeometryShader, int pass)
{
RenderTargetContext.SetRenderTargetContext(destinations);
if(useGeometryShader)
{
material.SetPass(pass);
#if UNITY_2019_1_OR_NEWER
Graphics.DrawProceduralNow(MeshTopology.Points, 1);
#else
Graphics.DrawProcedural(MeshTopology.Points, 1);
#endif
}
else
{
/*
GL.Clear(true, true, Color.clear);
GL.PushMatrix();
GL.LoadOrtho();
material.SetPass(pass);
GL.Begin(GL.TRIANGLE_STRIP);
GL.Vertex3(-1.0f, -1.0f, 0.1f);
GL.Vertex3(3.0f, -1.0f, 0.1f);
GL.Vertex3(-1.0f, 3.0f, 0.1f);
GL.End();
GL.PopMatrix();
*/
material.SetPass(pass);
Graphics.DrawMeshNow(screenMesh, Vector3.zero, Quaternion.identity);
}
}
/// <summary>
/// Compute the currently setuped render context with its targets
/// </summary>
/// <param name="cmd"></param>
/// <param name="computeShader"></param>
/// <param name="kernelIndex"></param>
/// <param name="computeThreadGroups"></param>
internal static void Draw(this CommandBuffer cmd, List<RenderTarget> destinations, ComputeShader computeShader, int kernelIndex, RenderDimension computeThreadGroups)
{
//cmd.SetRenderTargetContext(destinations);
cmd.DispatchCompute(computeShader, kernelIndex, computeThreadGroups.width, computeThreadGroups.height, 1);
}
internal static void Draw(List<RenderTarget> destinations, ComputeShader computeShader, int kernelIndex, RenderDimension computeThreadGroups)
{
//RenderTargetContext.SetRenderTargetContext(destinations);
computeShader.Dispatch(kernelIndex, computeThreadGroups.width, computeThreadGroups.height, 1);
}
/// <summary>
/// Scaling size correctly, need if single pass stereo is enabled
/// </summary>
/// <param name="cameraIsStereo"></param>
/// <param name="size"></param>
/// <param name="scale"></param>
/// <returns></returns>
private static int SinglePassStereoDownscale(bool cameraIsStereo, int size, int scale)
{
//using single pass stereo can introduce some Texeloffset which makes the rendering occur on the wrong place
//This happens because the samples are build on base of different mip levels
//single pass stereo TexelSize needs to be adjusted in the shader too
#if UNITY_2017_1_OR_NEWER
return cameraIsStereo && PipelineProperties.singlePassStereoDoubleWideEnabled && ((size / 2) % 2 > 0) ? 1 + size / scale : size / scale;
#else
return size / scale;
#endif
}
/// <summary>
/// Update a mip based render context array
/// </summary>
/// <param name="camera"></param>
/// <param name="renderContexts"></param>
/// <param name="rawDimension"></param>
/// <param name="levels"></param>
/// <param name="format"></param>
/// <param name="depthBufferBits"></param>
/// <param name="enableRandomWrite"></param>
internal static void UpdateMipRenderContext(this ICameraData cameraData, RenderContext[] renderContexts, RenderDimension rawDimension, int levels, RenderTextureFormat format, int depthBufferBits, bool enableRandomWrite)
{
for(int i = 0; i < levels; i++)
{
renderContexts[i].UpdateRenderContext(cameraData, format, depthBufferBits, enableRandomWrite, rawDimension);
rawDimension.width = Mathf.Max(SinglePassStereoDownscale(cameraData.GetStereoEnabled(), rawDimension.width, 2), 1);
rawDimension.height = Mathf.Max(rawDimension.height / 2, 1);
}
}
/// <summary>
/// Get a temporary render texture
/// </summary>
/// <param name="renderContext"></param>
/// <param name="format"></param>
/// <returns></returns>
internal static RenderTexture GetTemporary(RenderContext renderContext, RenderTextureFormat format)
{
#if UNITY_2017_1_OR_NEWER
return RenderTexture.GetTemporary(renderContext.descriptor);
#else
RenderTexture renderTexture = RenderTexture.GetTemporary(renderContext.width, renderContext.height, 16, format, RenderTextureReadWrite.Default, 1);
//renderTexture.enableRandomWrite = renderContext.enableRandomWrite;
return renderTexture;
#endif
}
}
}