Skip to content

[HDRP][Compositor] Fix outlines in transitions between post-processed and plain regions #1972

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 4 commits into from
Oct 3, 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 @@ -128,6 +128,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed error Maximum allowed thread group count is 65535 when resolution is very high.
- LOD meshes are now properly stripped based on the maximum lod value parameters contained in the HDRP asset.
- 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).

### 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 @@ -30,6 +30,7 @@ static partial class Styles
static public readonly GUIContent k_AAMode = EditorGUIUtility.TrTextContent("Post Anti-aliasing", "To override the postprocess Anti-aliasing mode, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_CullingMask = EditorGUIUtility.TrTextContent("Culling Mask", "To override the culling mask, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_VolumeMask = EditorGUIUtility.TrTextContent("Volume Mask", "To override the volume mask, activate the option by clicking on the check-box and then select the desired value.");
static public readonly GUIContent k_AlphaRange = EditorGUIUtility.TrTextContent("Alpha Range", "The range of alpha values used when transitioning from post-processed to plain image regions. A smaller range will result in a steeper transition.");

static public readonly string k_AlphaInfoPost = "The use of AOVs properties in a player require to to enable the Runtime AOV API support in the HDRP quality settings.";

Expand Down Expand Up @@ -178,6 +179,58 @@ public static void DrawStackedLayerProperties(Rect rect, SerializedCompositionLa
rect.y += CompositorStyle.k_Spacing;

EditorGUI.PropertyField(rect, serializedProperties.clearAlpha, Styles.k_ClearAlpha);
rect.y += 1.0f * CompositorStyle.k_Spacing;

// Draw a min/max slider for tha alpha range
{
const float spacing = 5;
var labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height);
EditorGUI.PrefixLabel(labelRect, Styles.k_AlphaRange);

var minLabelRect = rect;
minLabelRect.x += EditorGUIUtility.labelWidth;
minLabelRect.width = EditorGUIUtility.fieldWidth / 2;
serializedProperties.alphaMin.floatValue = EditorGUI.FloatField(minLabelRect, serializedProperties.alphaMin.floatValue);

GUI.SetNextControlName("AlphaMinMaxSlider");
var sliderRect = rect;
sliderRect.x += EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth / 2 + spacing;
sliderRect.width -= (EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + 2 * spacing);
float minVal = serializedProperties.alphaMin.floatValue;
float maxVal = serializedProperties.alphaMax.floatValue;

EditorGUI.MinMaxSlider(sliderRect, ref minVal, ref maxVal, 0, 1);
if (serializedProperties.alphaMin.floatValue != minVal || serializedProperties.alphaMax.floatValue != maxVal)
{
// Note: We need to move the focus when the slider changes, otherwise the textField will not update
GUI.FocusControl("AlphaMinMaxSlider");
serializedProperties.alphaMin.floatValue = minVal;
serializedProperties.alphaMax.floatValue = maxVal;
}

var maxLabelRect = rect;
maxLabelRect.x = sliderRect.x + sliderRect.width + spacing;
maxLabelRect.width = EditorGUIUtility.fieldWidth / 2;
serializedProperties.alphaMax.floatValue = EditorGUI.FloatField(maxLabelRect, serializedProperties.alphaMax.floatValue);

// sanity checks
if (serializedProperties.alphaMax.floatValue < serializedProperties.alphaMin.floatValue)
{
serializedProperties.alphaMax.floatValue = serializedProperties.alphaMin.floatValue;
}
if (serializedProperties.alphaMax.floatValue > 1)
{
serializedProperties.alphaMax.floatValue = 1;
}
if (serializedProperties.alphaMin.floatValue > serializedProperties.alphaMax.floatValue)
{
serializedProperties.alphaMin.floatValue = serializedProperties.alphaMax.floatValue;
}
if (serializedProperties.alphaMin.floatValue < 0)
{
serializedProperties.alphaMin.floatValue = 0;
}
}
rect.y += 1.5f * CompositorStyle.k_Spacing;

// The clear mode should be visible / configurable only for the first layer in the stack. For the other layers we set a camera-stacking specific clear-mode .
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal class SerializedCompositionLayer
public SerializedProperty aovBitmask;
public SerializedProperty inputFilters;
public SerializedProperty positionInStack;
public SerializedProperty alphaMin;
public SerializedProperty alphaMax;

public List<SerializedCompositionFilter> filterList = new List<SerializedCompositionFilter>();

Expand Down Expand Up @@ -60,6 +62,8 @@ public SerializedCompositionLayer(SerializedProperty root)
aovBitmask = root.FindPropertyRelative("m_AOVBitmask");
inputFilters = root.FindPropertyRelative("m_InputFilters");
positionInStack = root.FindPropertyRelative("m_LayerPositionInStack");
alphaMin = root.FindPropertyRelative("m_AlphaMin");
alphaMax = root.FindPropertyRelative("m_AlphaMax");

for (int index = 0; index < inputFilters.arraySize; index++)
{
Expand Down Expand Up @@ -91,7 +95,8 @@ public float GetPropertiesHeight()
EditorGUI.GetPropertyHeight(cullingMaskProperty, null) +
EditorGUI.GetPropertyHeight(volumeMask, null) +
EditorGUI.GetPropertyHeight(inputFilters, null) +
EditorGUIUtility.singleLineHeight * 7; //for the heading and pading
EditorGUI.GetPropertyHeight(alphaMin, null) + // we use a min/max slider in the UI so it takes a sinle line, so we don't need to count the alphaMax
EditorGUIUtility.singleLineHeight * 7; // for the heading and pading

if (inputFilters.arraySize > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ internal class AdditionalCompositorData : MonoBehaviour
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;
public float alphaMax = 1.0f;
public float alphaMin = 0.0f;

public void Init(List<CompositionFilter> layerFilters, bool clearAlpha)
{
Expand All @@ -36,6 +38,8 @@ public void ResetData()
layerFilters = null;
}

alphaMax = 1.0f;
alphaMin = 0.0f;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public float aspectRatio
// Returns true if this layer is using a camera that was cloned internally for drawing
bool isUsingACameraClone => !m_LayerCamera.Equals(m_Camera);

// The input alpha will be mapped between the min and max range when blending between the post-processed and plain image regions. This way the user can controls how steep is the transition.
[SerializeField] float m_AlphaMin = 0.0f;
[SerializeField] float m_AlphaMax = 1.0f;

private CompositorLayer()
{
}
Expand Down Expand Up @@ -469,6 +473,9 @@ public void SetAdditionalLayerData()
if (layerData != null)
{
layerData.Init(m_InputFilters, m_ClearAlpha);

layerData.alphaMin = m_AlphaMin;
layerData.alphaMax = m_AlphaMax;
}
}
}
Expand Down Expand Up @@ -507,7 +514,7 @@ public void UpdateOutputCamera()
if (m_Type == LayerType.Image)
{
var compositorData = m_LayerCamera.GetComponent<AdditionalCompositorData>();
if(compositorData)
if (compositorData)
compositorData.clearColorTexture = (m_Show && m_InputTexture != null) ? m_InputTexture : Texture2D.blackTexture;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -838,5 +838,28 @@ static public Camera GetSceceCamera()
static public CompositionManager GetInstance() =>
s_CompositorInstance ?? (s_CompositorInstance = GameObject.FindObjectOfType(typeof(CompositionManager), true) as CompositionManager);

static public Vector4 GetAlphaScaleAndBiasForCamera(HDCamera hdCamera)
{
AdditionalCompositorData compositorData = null;
hdCamera.camera.TryGetComponent<AdditionalCompositorData>(out compositorData);

if (compositorData)
{
float alphaMin = compositorData.alphaMin;
float alphaMax = compositorData.alphaMax;

if (alphaMax == alphaMin)
alphaMax += 0.0001f; // Mathf.Epsilon is too small and in this case it creates precission issues

float alphaScale = 1.0f / (alphaMax - alphaMin);
float alphaBias = -alphaMin * alphaScale;

return new Vector4(alphaScale, alphaBias, 0.0f, 0.0f);
}

// No compositor-specific data for this camera/layer, just return the default/neutral scale and bias
return new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,8 @@ struct UberPostParameters
public Vector4 bloomBicubicParams;
public Vector4 bloomDirtTileOffset;
public Vector4 bloomThreshold;

public Vector4 alphaScaleBias;
}

UberPostParameters PrepareUberPostParameters(HDCamera hdCamera, bool isSceneView)
Expand Down Expand Up @@ -918,10 +920,23 @@ UberPostParameters PrepareUberPostParameters(HDCamera hdCamera, bool isSceneView
PrepareChromaticAberrationParameters(ref parameters, featureFlags);
PrepareVignetteParameters(ref parameters, featureFlags);
PrepareUberBloomParameters(ref parameters, hdCamera);
PrepareAlphaScaleParameters(ref parameters, hdCamera);

return parameters;
}

void PrepareAlphaScaleParameters(ref UberPostParameters parameters, HDCamera camera)
{
if (m_EnableAlpha)
{
parameters.alphaScaleBias = Compositor.CompositionManager.GetAlphaScaleAndBiasForCamera(camera);
}
else
{
parameters.alphaScaleBias = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
}
}

static void DoUberPostProcess(in UberPostParameters parameters,
RTHandle source,
RTHandle destination,
Expand Down Expand Up @@ -956,6 +971,8 @@ static void DoUberPostProcess(in UberPostParameters parameters,
cmd.SetComputeVectorParam(parameters.uberPostCS, HDShaderIDs._BloomDirtScaleOffset, parameters.bloomDirtTileOffset);
cmd.SetComputeVectorParam(parameters.uberPostCS, HDShaderIDs._BloomThreshold, parameters.bloomThreshold);

// Alpha scale and bias (only used when alpha is enabled)
cmd.SetComputeVectorParam(parameters.uberPostCS, HDShaderIDs._AlphaScaleBias, parameters.alphaScaleBias);

// Dispatch uber post
cmd.SetComputeVectorParam(parameters.uberPostCS, "_DebugFlags", new Vector4(parameters.outputColorLog ? 1 : 0, 0, 0, 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ CBUFFER_START(cb0)
float4 _BloomDirtScaleOffset;
float4 _BloomBicubicParams;
float4 _DebugFlags;
float4 _AlphaScaleBias;
CBUFFER_END

#define DistCenter _DistortionParams1.xy
Expand Down Expand Up @@ -77,6 +78,9 @@ CBUFFER_END

#define OutputLogEnabled _DebugFlags.x

#define AlphaScale _AlphaScaleBias.x
#define AlphaBias _AlphaScaleBias.y

float2 DistortUV(float2 uv)
{
// Lens distortion
Expand Down Expand Up @@ -218,8 +222,10 @@ void Uber(uint3 dispatchThreadId : SV_DispatchThreadID)
// Alpha mask
#ifdef ENABLE_ALPHA
// Post processing is not applied on pixels with zero alpha
// The alpha scale and bias control how steep is the transition between the post-processed and plain regions
float alpha = inputColor.a * AlphaScale + AlphaBias;
// Saturate is necessary to avoid issues when additive blending pushes the alpha over 1.
color.xyz = lerp(inputColor.xyz, color.xyz, saturate(inputColor.a));
color.xyz = lerp(inputColor.xyz, color.xyz, saturate(alpha));
#endif

// Done
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,8 @@ static class HDShaderIDs
public static readonly int _ChromaSpectralLut = Shader.PropertyToID("_ChromaSpectralLut");
public static readonly int _ChromaParams = Shader.PropertyToID("_ChromaParams");

public static readonly int _AlphaScaleBias = Shader.PropertyToID("_AlphaScaleBias");

public static readonly int _VignetteParams1 = Shader.PropertyToID("_VignetteParams1");
public static readonly int _VignetteParams2 = Shader.PropertyToID("_VignetteParams2");
public static readonly int _VignetteColor = Shader.PropertyToID("_VignetteColor");
Expand Down