From 4849d85c55094a5300f4e3f0ced6e81667dcc0ab Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 27 Aug 2021 14:31:55 +0200 Subject: [PATCH 1/4] Add high quality antialiasing example using the accumulation api --- .../CHANGELOG.md | 1 + .../Documentation~/Accumulation.md | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 2f068d416b8..b8f3205976f 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -85,6 +85,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added a parameter to control the vertical shape offset of the volumetric clouds (case 1358528). - Added an option to render screen space global illumination in half resolution to achieve real-time compatible performance in high resolutions (case 1353727). - Added a built-in custom pass to draw object IDs. +- Added an example in the documentation that shows how to use the accumulation API for high quality antialiasing (supersampling). ### Fixed - Fixed Intensity Multiplier not affecting realtime global illumination. diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md index 366280fa873..a7eaa95b9f6 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md @@ -115,6 +115,115 @@ You can easily define the first three profiles without using an animation curve In this example, you can see that the slow open profile creates a motion trail appearance for the motion blur, which might be more desired for artists. On the other hand, the smooth open and close profile creates smoother animations than the slow open or uniform profiles. + +## High Quality Anti-aliasing wiht Accumulation +You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each renderer subframe. This is equivalent to rendering a higher resolution image and then downscaling to the final resolution, a process that is often callen **SuperSampling**. Using the accumulation API is preferable over rendering at higher resolutions, since it is using a much lower memory footprint. The following example shows how to properly setup the accumulation API from a script to perform high quality antialiasing: + +``` +public class SuperSampling : MonoBehaviour +{ + // The number of samples used for accumumation in the horizontal and verical directions. + public int samples = 8; + public bool saveToDisk = true; + + bool m_Recording = false; + int m_Iteration = 0; + int m_RecordedFrames = 0; + List m_OriginalProectionMatrix = new List(); + + [ContextMenu("Start Accumulation")] + void BeginAccumulation() + { + RenderPipelineManager.beginContextRendering += PrepareSubFrameCallBack; + RenderPipelineManager.endContextRendering += EndSubFrameCallBack; + HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline; + renderPipeline.BeginRecording(samples * samples, 1, 0.0f, 1.0f); + m_Recording = true; + m_Iteration = 0; + m_RecordedFrames = 0; + } + + [ContextMenu("Stop Accumulation")] + void StopAccumulation() + { + RenderPipelineManager.beginContextRendering -= PrepareSubFrameCallBack; + RenderPipelineManager.endContextRendering -= EndSubFrameCallBack; + HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline; + renderPipeline?.EndRecording(); + m_Recording = false; + } + + Matrix4x4 GetJitteredProjectionMatrix(Camera camera) + { + int totalSamples = samples * samples; + int subframe = m_Iteration % totalSamples; + int stratumX = subframe % samples; + int stratumY = subframe / samples; + float jitterX = stratumX * (1.0f / samples) - 0.5f; + float jitterY = stratumY * (1.0f / samples) - 0.5f; + var planes = camera.projectionMatrix.decomposeProjection; + + float vertFov = Mathf.Abs(planes.top) + Mathf.Abs(planes.bottom); + float horizFov = Mathf.Abs(planes.left) + Mathf.Abs(planes.right); + + var planeJitter = new Vector2(jitterX * horizFov / camera.pixelWidth, + jitterY * vertFov / camera.pixelHeight); + + planes.left += planeJitter.x; + planes.right += planeJitter.x; + planes.top += planeJitter.y; + planes.bottom += planeJitter.y; + + return Matrix4x4.Frustum(planes); + } + + void PrepareSubFrameCallBack(ScriptableRenderContext cntx, List cameras) + { + HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline; + if (renderPipeline != null && m_Recording) + { + renderPipeline.PrepareNewSubFrame(); + m_Iteration++; + } + + m_OriginalProectionMatrix.Clear(); + foreach (var camera in cameras) + { + // Jitter the projection matrix + m_OriginalProectionMatrix.Add(camera.projectionMatrix); + camera.projectionMatrix = GetJitteredProjectionMatrix(camera); + } + + if (saveToDisk && m_Recording && m_Iteration % (samples * samples) == 0) + { + ScreenCapture.CaptureScreenshot($"frame_{m_RecordedFrames++}.png"); + } + } + + void EndSubFrameCallBack(ScriptableRenderContext cntx, List cameras) + { + for (int i=0; i < cameras.Count; ++i) + { + cameras[i].projectionMatrix = m_OriginalProectionMatrix[i]; + } + } + + void OnDestroy() + { + if (m_Recording) + { + StopAccumulation(); + } + } + + void OnValidate() + { + // Make sure that we have at least one sample + samples = Mathf.Max(1, samples); + } +} +``` + ## Limitations The multi-frame rendering API internally changes the `Time.timeScale` of the Scene. This means that: - You cannot have different accumulation motion blur parameters per camera. From 9c3e345ef8b0be8740ecc0dc33b9722d66dd9d3e Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 3 Sep 2021 10:01:19 +0200 Subject: [PATCH 2/4] Review feedback --- .../Documentation~/Accumulation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md index a7eaa95b9f6..f0818ff9e93 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md @@ -117,9 +117,9 @@ In this example, you can see that the slow open profile creates a motion trail a ## High Quality Anti-aliasing wiht Accumulation -You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each renderer subframe. This is equivalent to rendering a higher resolution image and then downscaling to the final resolution, a process that is often callen **SuperSampling**. Using the accumulation API is preferable over rendering at higher resolutions, since it is using a much lower memory footprint. The following example shows how to properly setup the accumulation API from a script to perform high quality antialiasing: +You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each renderer subframe. This is equivalent to rendering a higher resolution image, then downscaling to the final resolution, a process that is often called **SuperSampling**. UThe accumulation API uses fewer memory resources in the GPU than rendering at higher resolutions. The following example shows how to perform high quality antialiasing with the accumulation API from a script: -``` +```C# public class SuperSampling : MonoBehaviour { // The number of samples used for accumumation in the horizontal and verical directions. From 7214c0cebdbb52903b7d077ed5a3f16f8e48a3e8 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Fri, 3 Sep 2021 10:07:59 +0200 Subject: [PATCH 3/4] Fix small typo --- .../Documentation~/Accumulation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md index f0818ff9e93..5d8a3684945 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md @@ -117,7 +117,7 @@ In this example, you can see that the slow open profile creates a motion trail a ## High Quality Anti-aliasing wiht Accumulation -You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each renderer subframe. This is equivalent to rendering a higher resolution image, then downscaling to the final resolution, a process that is often called **SuperSampling**. UThe accumulation API uses fewer memory resources in the GPU than rendering at higher resolutions. The following example shows how to perform high quality antialiasing with the accumulation API from a script: +You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each rendered subframe. This is equivalent to rendering a higher resolution image, then downscaling to the final resolution, a process that is often called **SuperSampling**. The accumulation API uses fewer memory resources in the GPU than rendering at higher resolutions. The following example shows how to perform high quality antialiasing with the accumulation API from a script: ```C# public class SuperSampling : MonoBehaviour From 9ced11922f31925f4cb0091c4270faba3dc97d9d Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Mon, 13 Sep 2021 11:59:44 +0200 Subject: [PATCH 4/4] Review feedback --- .../Documentation~/Accumulation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md index 5d8a3684945..8acb4096a32 100644 --- a/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md +++ b/com.unity.render-pipelines.high-definition/Documentation~/Accumulation.md @@ -117,7 +117,7 @@ In this example, you can see that the slow open profile creates a motion trail a ## High Quality Anti-aliasing wiht Accumulation -You can also use the accumulation API to get a high quality antialiased frame by jittering the projection matrix of each rendered subframe. This is equivalent to rendering a higher resolution image, then downscaling to the final resolution, a process that is often called **SuperSampling**. The accumulation API uses fewer memory resources in the GPU than rendering at higher resolutions. The following example shows how to perform high quality antialiasing with the accumulation API from a script: +You can also use the accumulation API to jitter the projection matrix of each rendered subframe and get a high quality antialiased frame. This is equivalent to rendering a higher resolution image, then downscaling to the final resolution, a process that is often called **SuperSampling**. The accumulation API uses fewer memory resources in the GPU than rendering at higher resolutions. The following example shows how to perform high quality antialiasing with the accumulation API from a script: ```C# public class SuperSampling : MonoBehaviour