Skip to content
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

Added an emissive as forward pass when the lit is in deferred mode. #2527

Closed
wants to merge 2 commits into from

Conversation

anisunity
Copy link
Contributor

@anisunity anisunity commented Nov 4, 2020

In order to properly support APV and SSGI(RTGI). We need to be able to not impact the emissive when in deferred mode. To do so, we added the option to have the emissive rendered in a seperate forward pass only for object that have non null (default value SG or shader) or with a branch plugged in (SG).
This is only possible when the lit model is in deferred and if the matching frame setting is enabled.
The proper migration code has been implemented for both SG and regular shaders.
The pass is not generated for shader graph if the emissive value is black or nothing is plugged in the master node on the emission port.
The pass is disabled on materials that have null emissive values.
The code has not been backported to the non rendergraph path.

Testing status
Ran the tests with and without the feature locally they are all green (had to fix some tests that had issues in the scenes).

QA plan test:
This PR introduce a new pass to render Emissive Color in a new pass but only for Lit Material with a Surface Type Opaque.
There is a new FrameSettings: LitEmissiveAsForward which allow to control if the Emissive contribution of a Material will be rendering into the Lighting Buffer during the GBuffer pass or in an extra Emissive Color pass which is after all the other lighting.
This change of rendering order only apply for objcet render in the deferred pass; Transparent Material or other Material (hair, stacklit, fabric, eye, axf, unlit) aren't affected.

Plan test:

  • Yamato test already validated that by default nothing change compare to before this PR. Executed code should be exactly the same with same result and no Forward Emissive Pass executed.
  • When enabling LitEmissiveAsForward in a scene with Lit emissive objects, we should get the same visual result. However there is a difference, now the SSAO algorithm will not affect the emissive and in addition, if two emissive object are on top of each other, they will contribute twice (against one without the change). The new pass can be check in a RenderDoc capture or the FrameDebugger. If Lit Material don't have a Emissive contribution, then nothing should be render in this extra pass.
  • It can be validated that it work correctly with the SSGI effect. SSGI effect by default remove emissive contribution of object. With the FrameSetting on, it will work as expected.

@anisunity anisunity added the HDRP label Nov 4, 2020
@anisunity anisunity requested review from sebastienlagarde and a team November 4, 2020 17:30
@anisunity anisunity self-assigned this Nov 4, 2020
@TomasKiniulis
Copy link
Contributor

Hey @anisunity not quite clear from the description what needs testing here. Notes to QA what are the things that need attention would be appreciated.

@@ -105,6 +105,9 @@ public enum FrameSettingsField
/// <summary>When enabled, Cameras using these Frame Settings use Alpha To Mask. Activate MSAA to access this option.</summary>
[FrameSettingsField(0, displayedName: "Alpha To Mask", positiveDependencies: new[] { MSAA }, customOrderInGroup: 3, tooltip: "When enabled, Cameras using these Frame Settings use Alpha To Mask. Activate MSAA to access this option.")]
AlphaToMask = 56,
/// <summary>When enabled, The emissive part of the materials is rendered as a forward pass for the deferred pipeline.</summary>
[FrameSettingsField(0, displayedName: "Emissive as Forward", positiveDependencies: new[] { LitShaderMode }, customOrderInGroup: 3, tooltip: "When enabled, The emissive part of the materials is rendered as a forward pass for the deferred pipeline.")]
EmissiveAsForward = 57,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you name it "LitEmissiveAsForward" so we understand it is only for the Lit shader. Thanks

@anisunity
Copy link
Contributor Author

The pr is still not done, missing some comments and the tesselation versions of some shaders

}

if (emissionPassCanBeDisabled)
material.SetShaderPassEnabled(HDShaderPassNames.s_ForwardEmissiveStr, emissiveIsActive);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test what happens when you create a material with a Lit shader (emission is back and the pass is disabled) and then assign a shader graph set up in a way that the emission pass is enabled?
This is a pretty common use case because when we create a material it has the lit shader by default.

@@ -756,6 +759,7 @@ internal static void Sanitize(ref FrameSettings sanitizedFrameSettings, Camera c
// TODO: The work will be implemented piecemeal to support all passes
bool msaa = sanitizedFrameSettings.bitDatas[(int)FrameSettingsField.MSAA] &= renderPipelineSettings.supportMSAA && sanitizedFrameSettings.litShaderMode == LitShaderMode.Forward && !pipelineSupportsRayTracing;
sanitizedFrameSettings.bitDatas[(int)FrameSettingsField.AlphaToMask] &= msaa;
sanitizedFrameSettings.bitDatas[(int)FrameSettingsField.LitEmissiveAsForward] &= sanitizedFrameSettings.litShaderMode == LitShaderMode.Deferred;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see above that the emissive pass feature doesn't work if the frame settings OpaqueObjects is disabled. Maybe it's worth to add it here in the sanitize?

Copy link
Contributor

@remi-chapelain remi-chapelain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, is there a reason why we disable this by default ? It looks like it's an improvement that users would want since the previous way of dealing with it was making a compromise by sharing a buffer for emissive and GI. Is it because of performance ? From what I've checked profiling the forward emissive pass it looks like the cost is negligible (it only adds 0.03ms on the simple scene I've checked.

What I've tested :

  • Emissive contribution of the object is restored with the new pass for SSGI/RTGI ✔️
  • Duplicating emissive object in place now contribute twice as much ✔️
  • Tested that the pass is automatically disabled in forward ✔️
  • Tested that the pass appear/disappear in RenderGraph ✔️
  • Tested that the materials not supported does not throw any errors (other shaders, transparents) ✔️

What went wrong :

  • Tested Antoine's method (desribed above) to create a material and got a failure, material stays black and emissive is not taken into account regardless of the color 🔴
  • Also, animating emissive color from a material that starts black does not work (via script), it only works if the material emissive color is not null at start.
    https://unity.gyazo.com/7f7094e5456b3ebe37aab13fd9852e66 🔴

@sebastienlagarde
Copy link
Collaborator

First, is there a reason why we disable this by default ? It looks like it's an improvement that users would want since the previous >way of dealing with it was making a compromise by sharing a buffer for emissive and GI. Is it because of performance ? From >what I've checked profiling the forward emissive pass it looks like the cost is negligible (it only adds 0.03ms on the simple scene >I've checked.

Yes. You pay a CPU cost (re-rendering mesh) + the GPU cost (rasterization of triangle). If you have a lot of Emissive heavy tessellated mesh it can become costly. Now this is a good remark and if we can simplify our codebase, then maybe we should consider to have it all the time. Let me think about it.


// We need to grab the emission block to check if it is connected, or the default value is non null.
bool emissionPassEnabled = false;
if (!context.connectedBlocks.Contains(BlockFields.SurfaceDescription.Emission))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't take care up to know, but is this code done for all shader or just lit shader? We must generate EmissiveForward pass only for lit shader.

@@ -88,5 +88,13 @@ public bool overrideBakedGI
get => m_OverrideBakedGI;
set => m_OverrideBakedGI = value;
}

[SerializeField]
bool m_EmissionOverriden;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it is not in lighting but should be in lit data itself (I don't remind if we have such a struct)

#endif
)
{
#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is many thing in this file that aren't appropriate as far as I can tell. Like many call to debug mode or motion vector.

@sebastienlagarde
Copy link
Collaborator

This should be replace by #2748

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants