//======= Copyright (c) Stereolabs Corporation, All rights reserved. =============== using UnityEngine; using UnityEngine.Rendering; /// /// Helper functions for the post processing effects applied to the final mixed reality image. /// Used by ZEDRenderingPlane when Post-Processing is enabled, and always used by GreenScreenManager. /// public class ZEDPostProcessingTools { /// /// Cached property ID for _horizontal. Use horizontalPropertyID property instead. /// private static int? _horizpropID; /// /// Cached shader ID for "_horizontal" property, to optimize shader assignment. /// We do this since this is a property we may set every frame. /// private static int horizontalPropertyID { get { if (_horizpropID == null) { _horizpropID = Shader.PropertyToID("horizontal"); } return (int)_horizpropID; } } /// /// Returns the gaussian value for f(x) = (1/2*3.14*s)*e(-x*x/(2*s)). /// /// /// /// public static float Gaussian(float x, float sigma) { return (1.0f / (2.0f * Mathf.PI * sigma)) * Mathf.Exp(-((x * x) / (2.0f * sigma))); } /// /// Computes weights to be sent to the blur shader. /// /// /// /// public static void ComputeWeights(float sigma, out float[] weights_, out float[] offsets_) { float[] weights = new float[5]; float[] offsets = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f }; weights_ = new float[5]; offsets_ = new float[5] { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f }; // Calculate the weights weights[0] = Gaussian(0, sigma); if (sigma != 0) { float sum = weights[0]; for (int i = 1; i < 5; ++i) { weights[i] = Gaussian(offsets[i], sigma); sum += 2.0f * weights[i]; } for (int i = 0; i < 5; ++i) { weights[i] /= sum; } //Fix for just 3 fetches weights_[0] = weights[0]; weights_[1] = weights[1] + weights[2]; weights_[2] = weights[3] + weights[4]; offsets_[0] = 0.0f; offsets_[1] = ((weights[1] * offsets[1]) + (weights[2] * offsets[2])) / weights_[1]; offsets_[2] = ((weights[3] * offsets[3]) + (weights[4] * offsets[4])) / weights_[2]; } } /// /// Blurs a render texture. /// /// Source RenderTexture. /// RenderTexture that the blurred version will be rendered into. /// Material used to blur. /// The pass used by the material. /// More iterations means a more prominent blur. /// The downscale of the source, which increases blur and decreases computation time. public static void Blur(RenderTexture source, RenderTexture dest, Material mat, int pass, int numberIterations = -1, int downscale = 2) { if (numberIterations == -1 || numberIterations == 0) { Graphics.Blit(source, dest, mat, pass); return; } RenderTexture buffer = RenderTexture.GetTemporary(source.width / downscale, source.height / downscale, source.depth, source.format, RenderTextureReadWrite.Default); if (mat == null) { Graphics.Blit(source, buffer); Graphics.Blit(buffer, dest); } else { bool oddEven = false; //Create two buffers to make a multi-pass blur. RenderTexture buffer2 = RenderTexture.GetTemporary(source.width / downscale, source.height / downscale, source.depth, source.format, RenderTextureReadWrite.Default); Graphics.Blit(source, buffer); //To each pass, alternate the buffer, and set the blur direction. for (int i = 0; i < numberIterations * 2; i++) { //mat.SetInt("horizontal", System.Convert.ToInt32(oddEven)); mat.SetInt(horizontalPropertyID, System.Convert.ToInt32(oddEven)); if (i < numberIterations * 2 - 1) { Graphics.Blit(oddEven ? buffer2 : buffer, !oddEven ? buffer2 : buffer, mat, pass); oddEven = !oddEven; } else { //mat.SetInt("horizontal", System.Convert.ToInt32(oddEven)); mat.SetInt(horizontalPropertyID, System.Convert.ToInt32(oddEven)); //Copy the buffer to the final texture. if (oddEven) { Graphics.Blit(buffer2, dest, mat, pass); } else { Graphics.Blit(buffer, dest, mat, pass); } } } //Destroy all the temporary buffers. RenderTexture.ReleaseTemporary(buffer2); } RenderTexture.ReleaseTemporary(buffer); } /// /// Holds IDs of shader properties. Used because setting a property by ID is faster than /// setting it by a property name. /// static class Uniforms { internal static readonly int _MainTex = Shader.PropertyToID("_MainTex"); internal static readonly int _TempRT = Shader.PropertyToID("_TempRT"); internal static readonly int _TempRT2 = Shader.PropertyToID("_TempRT2"); internal static readonly int _TempRT3 = Shader.PropertyToID("_TempRT3"); } /// /// Blurs a render texture. /// /// CommandBuffer from where the rendertexture is taken. /// RenderTexture to be blurred. /// Material used to blur /// The pass used by the material /// More iterations means a more prominent blur /// The downscale of the source, which increases blur and decreases computation time. public static void Blur(CommandBuffer cb, RenderTexture texture, Material mat, int pass, int numberIterations = -1, int downscale = 2) { if (numberIterations == -1 || numberIterations == 0) { cb.GetTemporaryRT(Uniforms._TempRT, texture.width, texture.height, texture.depth); cb.Blit(texture, Uniforms._TempRT, mat, pass); cb.Blit(Uniforms._TempRT, texture); cb.ReleaseTemporaryRT(Uniforms._TempRT); return; } cb.GetTemporaryRT(Uniforms._TempRT, texture.width / downscale, texture.height / downscale, texture.depth, FilterMode.Bilinear, texture.format, RenderTextureReadWrite.Default); cb.GetTemporaryRT(Uniforms._TempRT2, texture.width / downscale, texture.height / downscale, texture.depth, FilterMode.Bilinear, texture.format, RenderTextureReadWrite.Default); bool oddEven = false; //Create two buffers to make a multi-pass blur cb.Blit(texture, Uniforms._TempRT); //To each pass alternate the buffer, and set the blur direction for (int i = 0; i < numberIterations * 2; i++) { //mat.SetInt("horizontal", System.Convert.ToInt32(oddEven)); mat.SetInt(horizontalPropertyID, System.Convert.ToInt32(oddEven)); if (i < numberIterations * 2 - 1) { cb.Blit(oddEven ? Uniforms._TempRT2 : Uniforms._TempRT, !oddEven ? Uniforms._TempRT2 : Uniforms._TempRT, mat, pass); oddEven = !oddEven; } else { //mat.SetInt("horizontal", System.Convert.ToInt32(oddEven)); mat.SetInt(horizontalPropertyID, System.Convert.ToInt32(oddEven)); //Copy the buffer to the final texture if (oddEven) { cb.Blit(Uniforms._TempRT2, texture, mat, pass); } else { cb.Blit(Uniforms._TempRT, texture, mat, pass); } } } //Destroy all the temporary buffers cb.ReleaseTemporaryRT(Uniforms._TempRT); cb.ReleaseTemporaryRT(Uniforms._TempRT2); } public static void ComposeMask(CommandBuffer cb, RenderTexture mask, Material matStencilToMask, Material matComposeMask) { cb.GetTemporaryRT(Uniforms._TempRT, mask.width, mask.height, mask.depth, mask.filterMode, mask.format, RenderTextureReadWrite.Default); cb.GetTemporaryRT(Uniforms._TempRT2, -1, -1, 24); cb.Blit(mask, Uniforms._TempRT); //This is fine, set up the target and clear. cb.SetRenderTarget(Uniforms._TempRT2); cb.ClearRenderTarget(false, true, Color.black); //To keep the stencil in post process. cb.SetRenderTarget(Uniforms._TempRT2, BuiltinRenderTextureType.CurrentActive); cb.Blit(BuiltinRenderTextureType.CameraTarget, Uniforms._TempRT2, matStencilToMask); //Compose the second mask retrieved in the forward pass. The shader should set the stencil to 148. //cb.Blit(mask, Uniforms._TempRT); cb.SetGlobalTexture("_Mask", Uniforms._TempRT); // matComposeMask.set("_Mask", Uniforms._TempRT); cb.Blit(Uniforms._TempRT2, mask, matComposeMask); } }