Skip to content

Commit a9394a5

Browse files
committed
Added a scene transparent depth prepass.
Did a few enhancements to the samples. Added TODOs to README.
1 parent 16c567c commit a9394a5

11 files changed

Lines changed: 244 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
### Added
9+
- Added a Scene Transparent Depth PrePass.
10+
11+
### Changed
12+
- Gradient Fog can now be used before or after the transparent pass.
13+
14+
### Fixed
15+
- Fixed after image popping on leaving the volume by changing the default time scale to 0.
16+
- Fixed scene shifting on the screen to the left with the Glitch effect.
17+
- Removed some visual artifacts from Edge Detection by making the depth threshold relative to the center pixel depth.
18+
719
## [1.0.0] - 2020-09-17
820
### Added
921
- Added the main functionality for custom post-processing as renderer future for URP.

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ Other custom effects in samples but not used in screenshots:
4949
* It failed with **Single-Pass Instanced** on **Mock HMD Loader**.
5050
* The `SceneNormals` renderer feature uses the override material in the drawing settings so it doesn't copy the original materials' parameters (e.g. normal maps and alpha clipping) and doesn't respect custom vertex shaders. This should be solved in URP 10.0 with the release of the `DepthNormalsPass` made for the SSAO feature.
5151

52+
## Features I hope to implement
53+
54+
- [ ] Global settings for `CustomPostProcessRenderer` to be set from the renderer feature instead of the volume component.
55+
- [ ] A Volumetric Light Effect as a sample.
56+
- [ ] The ability to add the same renderer multiple times under the same injection point (not sure yet if it is a good idea).
57+
5258
## How To Install
5359

5460
Follow the instructions from the Unity manual on [Installing from a Git URL](https://docs.unity3d.com/Manual/upm-ui-giturl.html) and insert the url:
@@ -231,6 +237,7 @@ We didn't explain some stuff here but you can see more in the samples:
231237
* Create temporary render targets inside the renderer (see [StreakEffect.cs](Samples~/Examples/Scripts/PostProcessing/StreakEffect.cs)).
232238
* Create persistent render targets inside the renderer (see [AfterImageEffect.cs](Samples~/Examples/Scripts/PostProcessing/AfterImageEffect.cs)).
233239
* Use a shader graph `Unlit shader` to create a post processing effect (see [GlitchEffect.cs](Samples~/Examples/Scripts/PostProcessing/GlitchEffect.cs)).
240+
* Use a renderer at multiple injection points (see [GradientFogEffect.cs](Samples~/Examples/Scripts/PostProcessing/GradientFogEffect.cs) and [GradientFog.shader](Samples~/Examples/Resources/Shaders/PostProcessing/GradientFog.shader)).
234241

235242
## Issues & Pull Requests
236243

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using System;
2+
3+
namespace UnityEngine.Rendering.Universal.PostProcessing
4+
{
5+
/// <summary>
6+
/// This renderer feature renders the depth of transparent objects to a texture named "_CameraTransparentDepthTexture"
7+
/// </summary>
8+
[Serializable]
9+
public class SceneTransparentDepth : ScriptableRendererFeature
10+
{
11+
12+
/// <summary>
13+
/// The render pass
14+
/// </summary>
15+
private TransparentDepthPass depthPass = null;
16+
17+
/// <summary>
18+
/// The render target for the scene transparent depth
19+
/// </summary>
20+
private RenderTargetHandle sceneTransparentDepthTexture = default;
21+
22+
/// <summary>
23+
/// Intializes the renderer feature resources
24+
/// </summary>
25+
public override void Create()
26+
{
27+
depthPass = new TransparentDepthPass(RenderPassEvent.AfterRenderingPrePasses, RenderQueueRange.transparent, -1);
28+
sceneTransparentDepthTexture.Init("_CameraTransparentDepthTexture");
29+
}
30+
31+
/// <summary>
32+
/// Here you can inject one or multiple render passes in the renderer.
33+
/// This method is called when setting up the renderer once per-camera.
34+
/// </summary>
35+
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
36+
{
37+
depthPass.Setup(sceneTransparentDepthTexture);
38+
renderer.EnqueuePass(depthPass);
39+
}
40+
}
41+
42+
/// <summary>
43+
/// Render all transparent objects that have a 'DepthOnly' pass into the given depth buffer.
44+
///
45+
/// You can use this pass to prime a depth buffer for subsequent rendering.
46+
/// Use it as a z-prepass, or use it to generate a depth buffer.
47+
///
48+
/// Code mostly copied from "DepthOnlyPass.cs" from the Universal Render Pipeline
49+
/// </summary>
50+
public class TransparentDepthPass : ScriptableRenderPass
51+
{
52+
int kDepthBufferBits = 32;
53+
54+
private RenderTargetHandle destination;
55+
56+
FilteringSettings m_FilteringSettings;
57+
const string m_ProfilerTag = "Transparent Depth Prepass";
58+
ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
59+
ShaderTagId m_ShaderTagId = new ShaderTagId("DepthOnly");
60+
61+
/// <summary>
62+
/// Create the TransparentDepthPass
63+
/// </summary>
64+
public TransparentDepthPass(RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask)
65+
{
66+
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
67+
renderPassEvent = evt;
68+
}
69+
70+
/// <summary>
71+
/// Configure the pass
72+
/// </summary>
73+
public void Setup( RenderTargetHandle destination)
74+
{
75+
this.destination = destination;
76+
}
77+
78+
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
79+
{
80+
RenderTextureDescriptor descriptor = cameraTextureDescriptor;
81+
descriptor.colorFormat = RenderTextureFormat.Depth;
82+
descriptor.depthBufferBits = kDepthBufferBits;
83+
descriptor.msaaSamples = 1;
84+
85+
cmd.GetTemporaryRT(destination.id, descriptor, FilterMode.Point);
86+
ConfigureTarget(destination.Identifier());
87+
ConfigureClear(ClearFlag.All, Color.black);
88+
}
89+
90+
/// <inheritdoc/>
91+
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
92+
{
93+
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
94+
using (new ProfilingScope(cmd, m_ProfilingSampler))
95+
{
96+
context.ExecuteCommandBuffer(cmd);
97+
cmd.Clear();
98+
99+
var sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;
100+
var drawSettings = CreateDrawingSettings(m_ShaderTagId, ref renderingData, sortFlags);
101+
drawSettings.perObjectData = PerObjectData.None;
102+
103+
ref CameraData cameraData = ref renderingData.cameraData;
104+
Camera camera = cameraData.camera;
105+
if (cameraData.isStereoEnabled)
106+
context.StartMultiEye(camera);
107+
108+
m_FilteringSettings.layerMask = camera.cullingMask;
109+
110+
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref m_FilteringSettings);
111+
112+
}
113+
context.ExecuteCommandBuffer(cmd);
114+
CommandBufferPool.Release(cmd);
115+
}
116+
117+
/// <inheritdoc/>
118+
public override void FrameCleanup(CommandBuffer cmd)
119+
{
120+
if (cmd == null)
121+
throw new ArgumentNullException("cmd");
122+
123+
if (destination != RenderTargetHandle.CameraTarget)
124+
{
125+
cmd.ReleaseTemporaryRT(destination.id);
126+
destination = RenderTargetHandle.CameraTarget;
127+
}
128+
}
129+
}
130+
}

Runtime/RenderFeatures/SceneTransparentDepth.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Samples~/Examples/Resources/Shaders/PostProcessing/EdgeDetection.shader

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
// Normal similarity is calculated using a dot product
8484
float normalSame = smoothstep(_Threshold.x, _Threshold.y, dot(center.xyz, neighborhood.xyz));
8585
// Depth similarity is calculated using absolute difference
86-
float depthSame = smoothstep(_Threshold.w, _Threshold.z, abs(center.w - neighborhood.w));
86+
float depthSame = smoothstep(_Threshold.w * center.w, _Threshold.z * center.w, abs(center.w - neighborhood.w));
8787
// Combine normal and depth sameness to get edge factor
8888
float edge = 1 - normalSame * depthSame;
8989

Samples~/Examples/Resources/Shaders/PostProcessing/Glitch.shadergraph

Lines changed: 25 additions & 13 deletions
Large diffs are not rendered by default.

Samples~/Examples/Resources/Shaders/PostProcessing/GradientFog.shader

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
HLSLINCLUDE
44
#include "Packages/com.yetman.render-pipelines.universal.postprocess/ShaderLibrary/Core.hlsl"
55
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
6+
7+
#if AFTER_TRANSPARENT_ON
8+
#include "Packages/com.yetman.render-pipelines.universal.postprocess/ShaderLibrary/DeclareTransparentDepthTexture.hlsl"
9+
#endif
610

711
TEXTURE2D_X(_MainTex);
812

@@ -32,6 +36,20 @@
3236
uint2 positionSS = uv * _ScreenSize.xy;
3337

3438
float depth = LoadSceneDepth(positionSS);
39+
40+
#if AFTER_TRANSPARENT_ON
41+
// If the fog is applied after the transparent pass,
42+
// the depth is sampled from both the opaque and transparent depth textures
43+
// and the nearest depth is selected.
44+
// TODO: This can be optimized to read from one texture if the scene transparent depth includes the opaque depth
45+
float transparentDepth = LoadSceneTransparentDepth(positionSS);
46+
#if UNITY_REVERSED_Z
47+
depth = max(depth, transparentDepth);
48+
#else
49+
depth = min(depth, transparentDepth);
50+
#endif
51+
#endif
52+
3553
float deviceDepth = ConvertZBufferToDeviceDepth(depth);
3654
float3 viewPos = ComputeViewSpacePosition(uv, deviceDepth, unity_CameraInvProjection);
3755
float distance = length(viewPos);
@@ -52,6 +70,8 @@
5270
Pass
5371
{
5472
HLSLPROGRAM
73+
#pragma multi_compile_local_fragment __ AFTER_TRANSPARENT_ON
74+
5575
#pragma vertex FullScreenTrianglePostProcessVertexProgram
5676
#pragma fragment GradientFogFragmentProgram
5777
ENDHLSL

Samples~/Examples/Scripts/PostProcessing/AfterImageEffect.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class AfterImageEffect : VolumeComponent
1717
public ColorParameter blend = new ColorParameter(Color.black, false, false, true);
1818

1919
[Tooltip("A scale for the time to convergence.")]
20-
public MinFloatParameter timeScale = new MinFloatParameter(1, 0);
20+
public MinFloatParameter timeScale = new MinFloatParameter(0, 0);
2121
}
2222

2323
// Define the renderer for the custom post processing effect
@@ -80,8 +80,8 @@ public override bool Setup(ref RenderingData renderingData, CustomPostProcessInj
8080
var stack = VolumeManager.instance.stack;
8181
// Get the corresponding volume component
8282
m_VolumeComponent = stack.GetComponent<AfterImageEffect>();
83-
// if blend value > 0, then we need to render this effect.
84-
bool requireRendering = m_VolumeComponent.blend.value != Color.black;
83+
// if blend value and time scale > 0, then we need to render this effect.
84+
bool requireRendering = m_VolumeComponent.blend.value != Color.black && m_VolumeComponent.timeScale.value > 0;
8585
// if we don't need to execute this frame, we need to make sure that the history is invalidated
8686
// this solves an artifact where a very old history is used due to the effect being disabled for many frames
8787
if(!requireRendering){
@@ -131,7 +131,7 @@ public override void Render(CommandBuffer cmd, RenderTargetIdentifier source, Re
131131
// set material properties
132132
if(m_Material != null){
133133
Color blend = m_VolumeComponent.blend.value;
134-
float power = Time.deltaTime / m_VolumeComponent.timeScale.value;
134+
float power = Time.deltaTime / Mathf.Max(Mathf.Epsilon, m_VolumeComponent.timeScale.value);
135135
// The amound of blending should depend on the delta time to make fading time frame-rate independent.
136136
blend.r = Mathf.Pow(blend.r, power);
137137
blend.g = Mathf.Pow(blend.g, power);

Samples~/Examples/Scripts/PostProcessing/GradientFogEffect.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public class GradientFogEffect : VolumeComponent
2929
}
3030

3131
// Define the renderer for the custom post processing effect
32-
[CustomPostProcess("Gradient Fog", CustomPostProcessInjectionPoint.AfterOpaqueAndSky)]
32+
// This effect can be used after the opaque/sky pass or after the transparent pass
33+
[CustomPostProcess("Gradient Fog", CustomPostProcessInjectionPoint.AfterOpaqueAndSky | CustomPostProcessInjectionPoint.BeforePostProcess)]
3334
public class GradientFogEffectRenderer : CustomPostProcessRenderer
3435
{
3536
// A variable to hold a reference to the corresponding volume component (you can define as many as you like)
@@ -79,6 +80,12 @@ public override void Render(CommandBuffer cmd, RenderTargetIdentifier source, Re
7980
m_Material.SetVector(ShaderIDs.ColorRange, new Vector2(m_VolumeComponent.nearColorDistance.value, m_VolumeComponent.farColorDistance.value));
8081
m_Material.SetColor(ShaderIDs.NearFogColor, m_VolumeComponent.nearFogColor.value);
8182
m_Material.SetColor(ShaderIDs.FarFogColor, m_VolumeComponent.farFogColor.value);
83+
// Checks whether the renderer is called before transparent or not to pick the proper shader features
84+
if(injectionPoint == CustomPostProcessInjectionPoint.AfterOpaqueAndSky){
85+
m_Material.DisableKeyword("AFTER_TRANSPARENT_ON");
86+
} else {
87+
m_Material.EnableKeyword("AFTER_TRANSPARENT_ON");
88+
}
8289
}
8390
// set source texture
8491
cmd.SetGlobalTexture(ShaderIDs.Input, source);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef YETMAN_POSTPROCESS_TRANSPARENT_DECLARE_DEPTH_TEXTURE_INCLUDED
2+
#define YETMAN_POSTPROCESS_TRANSPARENT_DECLARE_DEPTH_TEXTURE_INCLUDED
3+
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
4+
5+
TEXTURE2D_X_FLOAT(_CameraTransparentDepthTexture);
6+
SAMPLER(sampler_CameraTransparentDepthTexture);
7+
8+
float SampleSceneTransparentDepth(float2 uv)
9+
{
10+
return SAMPLE_TEXTURE2D_X(_CameraTransparentDepthTexture, sampler_CameraTransparentDepthTexture, UnityStereoTransformScreenSpaceTex(uv)).r;
11+
}
12+
13+
float LoadSceneTransparentDepth(uint2 uv)
14+
{
15+
return LOAD_TEXTURE2D_X(_CameraTransparentDepthTexture, uv).r;
16+
}
17+
#endif

0 commit comments

Comments
 (0)