Skip to content

Fixed LOD mesh stripping and LOD Group UI #2072

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 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
2 changes: 2 additions & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed accumulation on DX11
- Fixed issue with screen space UI not drawing on the graphics compositor (case 1279272).
- 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.

### 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 @@ -210,6 +210,13 @@ The tables that follow provide an overview of the **Features** that the High Def
| Hair | Not supported | Yes |
| Fabric | Not supported | Yes |

## LOD Management
In the Built-in Render Pipeline, you manage levels of detail (LOD) from the QualitySettings. Each quality setting defines a LOD Bias and a Maximum LOD value. As such, they are global to the quality setting and you cannot change them on a per camera basis. In HDRP, there are scalability settings that allow you to change the LOD settings per camera by using either predetermined values contained in the HDRP Asset of the current quality level or overridden values. For more information, see [HDRP Asset](HDRP-Asset.md) and [Frame Settings](Frame-Settings.md).

Managing LOD in this way has two consequences:
- Default LOD settings for a quality level are now stored in the HDRP Asset instead of the Quality Settings.
- Built-in APIs such as QualitySettings.lodBias or QualitySettings.maximumLODLevel no longer work. Instead, you need to change these properties through the camera Frame Settings. If you use the Built-in APIs, they have no effect at all.

## Render Pipeline Hooks

| **Feature** | **Built-in Render Pipeline** | **High Definition Render Pipeline (HDRP)** |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ class HDRPPreprocessBuild : IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }

int GetMinimumMaxLoDValue(HDRenderPipelineAsset asset)
{
int minimumMaxLoD = int.MaxValue;
var maxLoDs = asset.currentPlatformRenderPipelineSettings.maximumLODLevel;
var schema = ScalableSettingSchema.GetSchemaOrNull(maxLoDs.schemaId);
for (int lod = 0; lod < schema.levelCount; ++lod)
{
if (maxLoDs.TryGet(lod, out int maxLoD))
minimumMaxLoD = Mathf.Min(minimumMaxLoD, maxLoD);
}

if (minimumMaxLoD != int.MaxValue)
return minimumMaxLoD;
else
return 0;
}

public void OnPreprocessBuild(BuildReport report)
{
// Detect if the users forget to assign an HDRP Asset
Expand Down Expand Up @@ -38,16 +55,35 @@ public void OnPreprocessBuild(BuildReport report)

// If platform is supported all good
GraphicsDeviceType unsupportedGraphicDevice = GraphicsDeviceType.Null;
if (HDUtils.AreGraphicsAPIsSupported(report.summary.platform, out unsupportedGraphicDevice)
bool supported = HDUtils.AreGraphicsAPIsSupported(report.summary.platform, out unsupportedGraphicDevice)
&& HDUtils.IsSupportedBuildTarget(report.summary.platform)
&& HDUtils.IsOperatingSystemSupported(SystemInfo.operatingSystem))
return;
&& HDUtils.IsOperatingSystemSupported(SystemInfo.operatingSystem);

unsupportedGraphicDevice = (unsupportedGraphicDevice == GraphicsDeviceType.Null) ? SystemInfo.graphicsDeviceType : unsupportedGraphicDevice;
string msg = "The platform " + report.summary.platform.ToString() + " with the graphic API " + unsupportedGraphicDevice + " is not supported with High Definition Render Pipeline";
if (!supported)
{
unsupportedGraphicDevice = (unsupportedGraphicDevice == GraphicsDeviceType.Null) ? SystemInfo.graphicsDeviceType : unsupportedGraphicDevice;
string msg = "The platform " + report.summary.platform.ToString() + " with the graphic API " + unsupportedGraphicDevice + " is not supported with High Definition Render Pipeline";

// Throw an exception to stop the build
throw new BuildFailedException(msg);
// Throw an exception to stop the build
throw new BuildFailedException(msg);
}

// Update all quality levels with the right max lod so that meshes can be stripped.
// We don't take lod bias into account because it can be overridden per camera.
int qualityLevelCount = QualitySettings.names.Length;
for (int i = 0; i < qualityLevelCount; ++i)
{
QualitySettings.SetQualityLevel(i, false);
var renderPipeline = QualitySettings.renderPipeline as HDRenderPipelineAsset;
if (renderPipeline != null)
{
QualitySettings.maximumLODLevel = GetMinimumMaxLoDValue(renderPipeline);
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we need to revert this value somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thought about this but actually the Quality Settings are hidden to the users anyway and now we state clearly in the doc that they are not supported so using this API would not yield any result (since we override it for each camera afterward).
Also, now when we build a player we override all the various quality level parameters anyway for mesh stripping.

Copy link
Contributor

Choose a reason for hiding this comment

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

I know it is not an issue currently, but with pipeline interoperability, if you switch back to urp after having build HDRP, settings can be a mess. but let's not deal with it for now (but poke jenny about it :) )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, exact same problem as the skybox material. As long as we don't have proper APIs for that we are doomed to have the same issues everywhere.

}
else
{
QualitySettings.maximumLODLevel = GetMinimumMaxLoDValue(hdPipelineAsset);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ public HDRenderPipeline(HDRenderPipelineAsset asset, HDRenderPipelineAsset defau

SetRenderingFeatures();

// Initialize lod settings with the default frame settings. This will pull LoD values from the current quality level HDRP asset if necessary.
// This will make the LoD Group UI consistent with the scene view camera like it is for builtin pipeline.
QualitySettings.lodBias = m_Asset.GetDefaultFrameSettings(FrameSettingsRenderType.Camera).GetResolvedLODBias(m_Asset);
QualitySettings.maximumLODLevel = m_Asset.GetDefaultFrameSettings(FrameSettingsRenderType.Camera).GetResolvedMaximumLODLevel(m_Asset);

// The first thing we need to do is to set the defines that depend on the render pipeline settings
m_RayTracingSupported = GatherRayTracingSupport(m_Asset.currentPlatformRenderPipelineSettings);

Expand Down