123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- using System;
- using System.Runtime.CompilerServices;
- using UnityEngine;
- using UnityEngine.Experimental.Rendering;
- using UnityEngine.InputSystem.Interactions;
- using UnityEngine.Rendering;
- using UnityEngine.Rendering.Universal;
- using UnityEngine.Rendering.Universal.Internal;
- namespace SicknessReduction.Visual.Rendering
- {
- internal static class ShaderConstants
- {
- public static readonly int _FullCoCTexture = Shader.PropertyToID("_FullCoCTexture");
- public static readonly int _DofTexture = Shader.PropertyToID("_DofTexture");
- public static readonly int _CoCParams = Shader.PropertyToID("_CoCParams");
- public static readonly int _BokehKernel = Shader.PropertyToID("_BokehKernel");
- public static readonly int _PongTexture = Shader.PropertyToID("_PongTexture");
- public static readonly int _PingTexture = Shader.PropertyToID("_PingTexture");
- }
- class BokehRenderPass : ScriptableRenderPass
- {
- // used to label this pass in Unity's Frame Debug utility
- string profilerTag;
- private Material material;
- private Material uberMaterial;
- private BokehFeature.BokehFeatureSettings bokehSettings;
- private Vector4[] m_BokehKernel;
- private bool kernelPrepared;
- RenderTextureDescriptor m_Descriptor;
- RenderTargetIdentifier cameraColorTargetIdent;
- RenderTargetHandle target;
- private RenderTargetHandle tmp;
- public BokehRenderPass(string profilerTag,
- BokehFeature.BokehFeatureSettings settings)
- {
- this.profilerTag = profilerTag;
- renderPassEvent = settings.WhenToInsert;
- bokehSettings = settings;
- material = CoreUtils.CreateEngineMaterial(
- Shader.Find("Hidden/Universal Render Pipeline/BokehDepthOfField"));
- Debug.Log("Material created: " + material?.shader?.name ?? "Null");
- }
- public void Setup(in RenderTextureDescriptor baseDescriptor, RenderTargetIdentifier target)
- {
- //m_Descriptor = baseDescriptor;
- cameraColorTargetIdent = target;
- }
- // called each frame before Execute, use it to set up things the pass will need
- public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
- {
- int wh = m_Descriptor.width / 2;
- int hh = m_Descriptor.height / 2;
- /*cmd.GetTemporaryRT(ShaderConstants._FullCoCTexture,
- cameraTextureDescriptor);
- cmd.GetTemporaryRT(ShaderConstants._PingTexture,
- cameraTextureDescriptor);
- cmd.GetTemporaryRT(ShaderConstants._PongTexture,
- cameraTextureDescriptor);
- cmd.GetTemporaryRT(target.id, cameraTextureDescriptor);*/
- m_Descriptor = cameraTextureDescriptor;
- // Temporary textures
- cmd.GetTemporaryRT(ShaderConstants._FullCoCTexture,
- GetStereoCompatibleDescriptor(m_Descriptor.width, m_Descriptor.height, GraphicsFormat.R8_UNorm),
- FilterMode.Bilinear);
- cmd.GetTemporaryRT(ShaderConstants._PingTexture,
- GetStereoCompatibleDescriptor(wh, hh, GraphicsFormat.R16G16B16A16_SFloat), FilterMode.Bilinear);
- cmd.GetTemporaryRT(ShaderConstants._PongTexture,
- GetStereoCompatibleDescriptor(wh, hh, GraphicsFormat.R16G16B16A16_SFloat), FilterMode.Bilinear);
- cmd.GetTemporaryRT(target.id, cameraTextureDescriptor);
- cmd.GetTemporaryRT(tmp.id, cameraTextureDescriptor);
- }
- // Execute is called for every eligible camera every frame. It's not called at the moment that
- // rendering is actually taking place, so don't directly execute rendering commands here.
- // Instead use the methods on ScriptableRenderContext to set up instructions.
- // RenderingData provides a bunch of (not very well documented) information about the scene
- // and what's being rendered.
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- // fetch a command buffer to use
- CommandBuffer cmd = CommandBufferPool.Get(profilerTag);
- cmd.Clear();
- int wh = m_Descriptor.width / 2;
- int hh = m_Descriptor.height / 2;
- // "A Lens and Aperture Camera Model for Synthetic Image Generation" [Potmesil81]
- float maxCoC = bokehSettings.maxCoc;
- float P = bokehSettings.focusDistance;
- float maxRadius = GetMaxBokehRadiusInPixels(m_Descriptor.height);
- float rcpAspect = 1f / (wh / (float) hh);
- cmd.SetGlobalVector(ShaderConstants._CoCParams,
- new Vector4(P, maxCoC, maxRadius, rcpAspect));
- // Prepare the bokeh kernel constant buffer
- if (!kernelPrepared)
- {
- PrepareBokehKernel();
- kernelPrepared = true;
- }
- cmd.SetGlobalVectorArray(ShaderConstants._BokehKernel, m_BokehKernel);
- // Compute CoC
- cmd.Blit(cameraColorTargetIdent, ShaderConstants._FullCoCTexture, material, 0);
- cmd.SetGlobalTexture(ShaderConstants._FullCoCTexture,
- ShaderConstants._FullCoCTexture);
- // Downscale & prefilter color + coc
- cmd.Blit(cameraColorTargetIdent, ShaderConstants._PingTexture, material, 1);
- // Bokeh blur
- cmd.Blit(ShaderConstants._PingTexture, ShaderConstants._PongTexture,
- material, 2);
- // Post-filtering
- cmd.Blit(ShaderConstants._PongTexture,
- BlitDstDiscardContent(cmd, ShaderConstants._PingTexture), material, 3);
- // Composite
- cmd.SetGlobalTexture(ShaderConstants._DofTexture,
- ShaderConstants._PingTexture);
- cmd.Blit(cameraColorTargetIdent, BlitDstDiscardContent(cmd, target.Identifier()), material, 4);
- //cmd.Blit(tmp.Identifier(), target.Identifier(), material, 5);
- //cmd.SetGlobalTexture("_BlitTex", cameraColorTargetIdent);
- //cmd.Blit(target.Identifier(), cameraColorTargetIdent, uberMaterial);
- cmd.Blit(target.Identifier(), cameraColorTargetIdent);
- context.ExecuteCommandBuffer(cmd);
- // tidy up after ourselves
- cmd.Clear();
- CommandBufferPool.Release(cmd);
- }
- // called after Execute, use it to clean up anything allocated in Configure
- public override void FrameCleanup(CommandBuffer cmd)
- {
- // Cleanup
- cmd.ReleaseTemporaryRT(ShaderConstants._FullCoCTexture);
- cmd.ReleaseTemporaryRT(ShaderConstants._PingTexture);
- cmd.ReleaseTemporaryRT(ShaderConstants._PongTexture);
- cmd.ReleaseTemporaryRT(target.id);
- cmd.ReleaseTemporaryRT(tmp.id);
- }
- #region Depth Of Field
- void PrepareBokehKernel()
- {
- const int kRings = 4;
- const int kPointsPerRing = 7;
- // Check the existing array
- if (m_BokehKernel == null)
- m_BokehKernel = new Vector4[42];
- // Fill in sample points (concentric circles transformed to rotated N-Gon)
- int idx = 0;
- float bladeCount = 5f;
- float curvature = 0f;
- float rotation = 10f * Mathf.Deg2Rad;
- const float PI = Mathf.PI;
- const float TWO_PI = Mathf.PI * 2f;
- for (int ring = 1; ring < kRings; ring++)
- {
- float bias = 1f / kPointsPerRing;
- float radius = (ring + bias) / (kRings - 1f + bias);
- int points = ring * kPointsPerRing;
- for (int point = 0; point < points; point++)
- {
- // Angle on ring
- float phi = 2f * PI * point / points;
- // Transform to rotated N-Gon
- // Adapted from "CryEngine 3 Graphics Gems" [Sousa13]
- float nt = Mathf.Cos(PI / bladeCount);
- float dt = Mathf.Cos(phi - (TWO_PI / bladeCount) *
- Mathf.Floor((bladeCount * phi + Mathf.PI) / TWO_PI));
- float r = radius * Mathf.Pow(nt / dt, curvature);
- float u = r * Mathf.Cos(phi - rotation);
- float v = r * Mathf.Sin(phi - rotation);
- m_BokehKernel[idx] = new Vector4(u, v);
- idx++;
- }
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- static float GetMaxBokehRadiusInPixels(float viewportHeight)
- {
- // Estimate the maximum radius of bokeh (empirically derived from the ring count)
- const float kRadiusInPixels = 14f;
- return Mathf.Min(0.05f, kRadiusInPixels / viewportHeight);
- }
- RenderTextureDescriptor GetStereoCompatibleDescriptor()
- => GetStereoCompatibleDescriptor(m_Descriptor.width, m_Descriptor.height, m_Descriptor.graphicsFormat,
- m_Descriptor.depthBufferBits);
- RenderTextureDescriptor GetStereoCompatibleDescriptor(int width, int height, GraphicsFormat format,
- int depthBufferBits = 0)
- {
- // Inherit the VR setup from the camera descriptor
- var desc = m_Descriptor;
- desc.depthBufferBits = depthBufferBits;
- desc.msaaSamples = 1;
- desc.width = width;
- desc.height = height;
- desc.graphicsFormat = format;
- return desc;
- }
- private BuiltinRenderTextureType BlitDstDiscardContent(CommandBuffer cmd, RenderTargetIdentifier rt)
- {
- // We set depth to DontCare because rt might be the source of PostProcessing used as a temporary target
- // Source typically comes with a depth buffer and right now we don't have a way to only bind the color attachment of a RenderTargetIdentifier
- cmd.SetRenderTarget(new RenderTargetIdentifier(rt, 0, CubemapFace.Unknown, -1),
- RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
- RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
- return BuiltinRenderTextureType.CurrentActive;
- }
- #endregion
- }
- }
|