////////////////////////////////////////////////////// // MK Glow Extensions // // // // Created by Michael Kremmel // // www.michaelkremmel.de // // Copyright © 2020 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 { 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 } } /// /// Enable or disable a specific Shader keyword /// /// /// /// 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); } /// /// Draw the currently setuped render context with its targets /// /// /// /// /// internal static void Draw(this CommandBuffer cmd, List destinations, Material material, int pass, Rect viewport) { cmd.SetRenderTargetContext(destinations); cmd.SetViewport(viewport); cmd.DrawMesh(screenMesh, Matrix4x4.identity, material, 0, pass); } internal static void Draw(List destinations, Material material, int pass) { RenderTargetContext.SetRenderTargetContext(destinations); material.SetPass(pass); Graphics.DrawMeshNow(screenMesh, Vector3.zero, Quaternion.identity); } /// /// Scaling size correctly, need if single pass stereo is enabled /// /// /// /// /// 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 } /// /// Update a mip based render context array /// /// /// /// /// /// /// internal static void UpdateMipRenderContext(this MK.Glow.ICameraData cameraData, RenderContext[] renderContexts, RenderDimension rawDimension, int levels, RenderTextureFormat format, int depthBufferBits) { for(int i = 0; i < levels; i++) { renderContexts[i].UpdateRenderContext(cameraData, format, depthBufferBits, rawDimension); rawDimension.width = Mathf.Max(SinglePassStereoDownscale(cameraData.GetStereoEnabled(), rawDimension.width, 2), 1); rawDimension.height = Mathf.Max(rawDimension.height / 2, 1); } } /// /// Get a temporary render texture /// /// /// /// 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); return renderTexture; #endif } } }