Skip to content

[HDRP][Compositor] Fix camera stacking for AOVs in the graphics compositor #1912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed an inconsistency in the LOD group UI where LOD bias was not the right one.
- Fixed outlines in transitions between post-processed and plain regions in the graphics compositor (case 1278775).
- Fix decal being applied twice with LOD Crossfade.
- Fixed camera stacking for AOVs in the graphics compositor (case 1273223).

### Changed
- Preparation pass for RTSSShadows to be supported by render graph.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,17 @@ private void OnDestroy()
GraphData.onSaveGraph -= MarkShaderAsDirty;

Undo.undoRedoPerformed -= UndoCallback;
s_SelectionIndex = m_Editor.selectionIndex;
s_SelectionIndex = m_Editor ? m_Editor.selectionIndex : -1;
}

void UndoCallback()
{
// Undo-redo might change the layer order, so we need to redraw the compositor UI and also refresh the layer setup
if (!m_Editor)
{
return;
}

m_Editor.CacheSerializedObjects();
m_RequiresRedraw = true;
s_SelectionIndex = m_Editor.selectionIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal enum BackgroundFitMode
internal class AdditionalCompositorData : MonoBehaviour
{
public Texture clearColorTexture = null;
public RenderTexture clearDepthTexture = null;
public bool clearAlpha = true; // Clearing the alpha allows the post process to run only on the pixels covered by a stacked camera (and not the previous ones).
public BackgroundFitMode imageFitMode = BackgroundFitMode.Stretch;
public List<CompositionFilter> layerFilters;
Expand All @@ -29,6 +30,7 @@ public void Init(List<CompositionFilter> layerFilters, bool clearAlpha)
public void ResetData()
{
clearColorTexture = null;
clearDepthTexture = null;
clearAlpha = true;
imageFitMode = BackgroundFitMode.Stretch;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ public void SetupLayerCamera(CompositorLayer targetLayer, int layerPositionInSta
var cameraData = m_LayerCamera.GetComponent<HDAdditionalCameraData>();
m_LayerCamera.targetTexture = targetLayer.GetRenderTarget(false);

if (targetLayer.m_AOVBitmask == 0)
// Setup the custom clear pass for camera stacking
{
if (layerPositionInStack != 0)
{
Expand All @@ -625,7 +625,8 @@ public void SetupLayerCamera(CompositorLayer targetLayer, int layerPositionInSta
}
if (m_Type != LayerType.Image)
{
compositorData.clearColorTexture = targetLayer.GetRenderTarget(false);
compositorData.clearColorTexture = targetLayer.GetRenderTarget();
compositorData.clearDepthTexture = targetLayer.m_RTHandle;
}
cameraData.volumeLayerMask |= 1 << 31;
}
Expand All @@ -638,7 +639,7 @@ public void SetupLayerCamera(CompositorLayer targetLayer, int layerPositionInSta

// The target layer expects AOVs, so this stacked layer should also generate AOVs
int aovMask = (1 << (int)targetLayer.m_AOVBitmask);
if (aovMask > 1)
if (m_Show && aovMask > 1)
{
var aovRequestBuilder = new AOVRequestBuilder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -861,5 +861,39 @@ static public Vector4 GetAlphaScaleAndBiasForCamera(HDCamera hdCamera)
return new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
}

/// <summary>
/// For stacked cameras, returns the color buffer that will be used to draw on top
/// </summary>
/// <param name="hdCamera">The input camera</param>
/// <returns> The color buffer that will be used to draw on top, or null if not a stacked camera </returns>
static internal Texture GetClearTextureForStackedCamera(HDCamera hdCamera)
{
AdditionalCompositorData compositorData = null;
hdCamera.camera.TryGetComponent<AdditionalCompositorData>(out compositorData);

if (compositorData)
{
return compositorData.clearColorTexture;
}
return null;
}

/// <summary>
/// For stacked cameras, returns the depth buffer that will be used to draw on top
/// </summary>
/// <param name="hdCamera">The input camera</param>
/// <returns> The depth buffer that will be used to draw on top, or null if not a stacked camera </returns>
static internal RenderTexture GetClearDepthForStackedCamera(HDCamera hdCamera)
{
AdditionalCompositorData compositorData = null;
hdCamera.camera.TryGetComponent<AdditionalCompositorData>(out compositorData);

if (compositorData)
{
return compositorData.clearDepthTexture;
}
return null;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,15 @@ class DebugViewMaterialData
public RendererListHandle transparentRendererList;
public Material debugGBufferMaterial;
public FrameSettings frameSettings;

public Texture clearColorTexture;
public RenderTexture clearDepthTexture;
}

TextureHandle RenderDebugViewMaterial(RenderGraph renderGraph, CullingResults cull, HDCamera hdCamera)
{
bool msaa = hdCamera.frameSettings.IsEnabled(FrameSettingsField.MSAA);

var output = renderGraph.CreateTexture(
new TextureDesc(Vector2.one, true, true)
{
Expand Down Expand Up @@ -557,9 +561,19 @@ TextureHandle RenderDebugViewMaterial(RenderGraph renderGraph, CullingResults cu
rendererConfiguration: m_CurrentRendererConfigurationBakedLighting,
stateBlock: m_DepthStateOpaque)));

passData.clearColorTexture = Compositor.CompositionManager.GetClearTextureForStackedCamera(hdCamera); // returns null if is not a stacked camera
passData.clearDepthTexture = Compositor.CompositionManager.GetClearDepthForStackedCamera(hdCamera); // returns null if is not a stacked camera

builder.SetRenderFunc(
(DebugViewMaterialData data, RenderGraphContext context) =>
{
// If we are doing camera stacking, then we want to clear the debug color and depth buffer using the data from the previous camera on the stack
// Note: Ideally here we would like to draw directly on the same buffers as the previous camera, but currently the compositor is not using
// Texture Arrays so this would not work. We might need to revise this in the future.
if (data.clearColorTexture != null)
{
HDUtils.BlitColorAndDepth(context.cmd, data.clearColorTexture, data.clearDepthTexture, new Vector4(1, 1, 0, 0), 0, !hdCamera.clearDepth);
}
DrawOpaqueRendererList(context, data.frameSettings, data.opaqueRendererList);
DrawTransparentRendererList(context, data.frameSettings, data.transparentRendererList);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ internal static Volume GetOrCreateDefaultVolume()
Material m_Blit;
Material m_BlitTexArray;
Material m_BlitTexArraySingleSlice;
Material m_BlitColorAndDepth;
MaterialPropertyBlock m_BlitPropertyBlock = new MaterialPropertyBlock();

RenderTargetIdentifier[] m_MRTCache2 = new RenderTargetIdentifier[2];
Expand Down Expand Up @@ -327,6 +328,7 @@ internal int GetMaxScreenSpaceShadows()
string m_ForwardPassProfileName;

internal Material GetBlitMaterial(bool useTexArray, bool singleSlice) { return useTexArray ? (singleSlice ? m_BlitTexArraySingleSlice : m_BlitTexArray) : m_Blit; }
internal Material GetBlitColorAndDepthMaterial() { return m_BlitColorAndDepth; }

ComputeBuffer m_DepthPyramidMipLevelOffsetsBuffer = null;

Expand Down Expand Up @@ -1088,6 +1090,7 @@ void InitializeDebugMaterials()
m_DebugColorPicker = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugColorPickerPS);
m_DebugExposure = CoreUtils.CreateEngineMaterial(defaultResources.shaders.debugExposurePS);
m_Blit = CoreUtils.CreateEngineMaterial(defaultResources.shaders.blitPS);
m_BlitColorAndDepth = CoreUtils.CreateEngineMaterial(defaultResources.shaders.blitColorAndDepthPS);
m_ErrorMaterial = CoreUtils.CreateEngineMaterial("Hidden/InternalErrorShader");

// With texture array enabled, we still need the normal blit version for other systems like atlas
Expand Down Expand Up @@ -4080,8 +4083,16 @@ void RenderDebugViewMaterial(CullingResults cull, HDCamera hdCamera, ScriptableR
{
// When rendering debug material we shouldn't rely on a depth prepass for optimizing the alpha clip test. As it is control on the material inspector side
// we must override the state here.

CoreUtils.SetRenderTarget(cmd, m_CameraColorBuffer, m_SharedRTManager.GetDepthStencilBuffer(), ClearFlag.All, Color.clear);

// [case 1273223] When the camera is stacked on top of another one, we need to clear the debug view RT using the data from the previous camera in the stack
var clearColorTexture = Compositor.CompositionManager.GetClearTextureForStackedCamera(hdCamera); // returns null if is not a stacked camera
var clearDepthTexture = Compositor.CompositionManager.GetClearDepthForStackedCamera(hdCamera); // returns null if is not a stacked camera
if (clearColorTexture)
{
HDUtils.BlitColorAndDepth(cmd, clearColorTexture, clearDepthTexture, new Vector4(1, 1, 0, 0), 0, !hdCamera.clearDepth);
}

// Render Opaque forward
var rendererListOpaque = RendererList.Create(CreateOpaqueRendererListDesc(cull, hdCamera.camera, m_AllForwardOpaquePassNames, m_CurrentRendererConfigurationBakedLighting, stateBlock: m_DepthStateOpaque));
DrawOpaqueRendererList(renderContext, cmd, hdCamera.frameSettings, rendererListOpaque);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public sealed class ShaderResources
public Shader copyDepthBufferPS;
[Reload("Runtime/ShaderLibrary/Blit.shader")]
public Shader blitPS;
[Reload("Runtime/ShaderLibrary/BlitColorAndDepth.shader")]
public Shader blitColorAndDepthPS;

[Reload("Runtime/ShaderLibrary/DownsampleDepth.shader")]
public Shader downsampleDepthPS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,32 @@ public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scale
s_PropertyBlock.SetFloat(HDShaderIDs._BlitMipLevel, mipLevel);
BlitTexture(cmd, source, scaleBias, GetBlitMaterial(TextureXR.dimension), bilinear ? 1 : 0);
}

/// <summary>
/// Blit a 2D texture and depth buffer.
/// </summary>
/// <param name="cmd">Command Buffer used for rendering.</param>
/// <param name="sourceColor">Source Texture for color.</param>
/// <param name="sourceDepth">Source RenderTexture for depth.</param>
/// <param name="scaleBias">Scale and bias for sampling the input texture.</param>
/// <param name="mipLevel">Mip level to blit.</param>
/// <param name="bilinear">Enable bilinear filtering.</param>
internal static void BlitColorAndDepth(CommandBuffer cmd, Texture sourceColor, RenderTexture sourceDepth, Vector4 scaleBias, float mipLevel, bool blitDepth)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
if (hdPipeline != null)
{
Material mat = hdPipeline.GetBlitColorAndDepthMaterial();

s_PropertyBlock.SetFloat(HDShaderIDs._BlitMipLevel, mipLevel);
s_PropertyBlock.SetVector(HDShaderIDs._BlitScaleBias, scaleBias);
s_PropertyBlock.SetTexture(HDShaderIDs._BlitTexture, sourceColor);
if (blitDepth)
s_PropertyBlock.SetTexture(HDShaderIDs._InputDepth, sourceDepth, RenderTextureSubElement.Depth);
cmd.DrawProcedural(Matrix4x4.identity, mat, blitDepth ? 1 : 0, MeshTopology.Triangles, 3, 1, s_PropertyBlock);
}
}

/// <summary>
/// Blit a RTHandle texture
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ MonoBehaviour:
type: 3}
copyDepthBufferPS: {fileID: 4800000, guid: 42dfcc8fe803ece4096c58630689982f, type: 3}
blitPS: {fileID: 4800000, guid: 370f7a9cc4e362d488af024d371091e8, type: 3}
blitColorAndDepthPS: {fileID: 4800000, guid: c6e57f5bdbd2a284a86a3097c03884c8,
type: 3}
downsampleDepthPS: {fileID: 4800000, guid: 67d6171b0acc6554aad48c845ec7e67f, type: 3}
upsampleTransparentPS: {fileID: 4800000, guid: 2ad7ce40f0dbaf64dadef1f58d8524d3,
type: 3}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
Shader "Hidden/HDRP/BlitColorAndDepth"
{
HLSLINCLUDE

#pragma target 4.5
#pragma editor_sync_compilation
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch
#pragma multi_compile _ DISABLE_TEXTURE2D_X_ARRAY
#pragma multi_compile _ BLIT_SINGLE_SLICE
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"

TEXTURE2D (_BlitTexture);
TEXTURE2D (_InputDepthTexture);
SamplerState sampler_PointClamp;
SamplerState sampler_LinearClamp;
uniform float4 _BlitScaleBias;
uniform float _BlitMipLevel;

struct Attributes
{
uint vertexID : SV_VertexID;
UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};

Varyings Vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID) * _BlitScaleBias.xy + _BlitScaleBias.zw;
return output;
}

float4 FragColorOnly(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

return SAMPLE_TEXTURE2D_LOD(_BlitTexture, sampler_LinearClamp, input.texcoord.xy, _BlitMipLevel);
}

struct PixelData
{
float4 color : SV_Target;
float depth : SV_Depth;
};

PixelData FragColorAndDepth(Varyings input)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

PixelData pd;
pd.color = SAMPLE_TEXTURE2D_LOD(_BlitTexture, sampler_LinearClamp, input.texcoord.xy, _BlitMipLevel);
pd.depth = SAMPLE_TEXTURE2D_LOD(_InputDepthTexture, sampler_PointClamp, input.texcoord.xy, _BlitMipLevel).x;
return pd;
}

ENDHLSL

SubShader
{
Tags{ "RenderPipeline" = "HDRenderPipeline" }

// 0: Color Only
Pass
{
ZWrite Off ZTest Always Blend Off Cull Off

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragColorOnly
ENDHLSL
}

// 1: Color Only and Depth
Pass
{
ZWrite On ZTest Always Blend Off Cull Off

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragColorAndDepth
ENDHLSL
}

}

Fallback Off
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.