Runtime Actor Thumbnail Capture and Nanite

Hello!

I’m trying to setup a system for capturing thumbnails at runtime to allow us to display images of dynamic characters/objects on the UI (NPC menus, inventories etc).

The capture system handles requests for thumbnails by loading actors into a capture room located far below the map, where it waits for the actor to be fully loaded in before rendering them with a Scene Capture Component. The resulting render texture is then run through some post-processing materials before being passed over to the UI.

I have been following some of the advice shared on the threads started by [Eric [Content removed] and [Sam [Content removed] however similar to their experiences, I am struggling to ensure that actors that use Nanite meshes are of a sufficient/consistent quality, and unfortunately disabling Nanite is not an option.

Here’s some rough pseudo code outlining my current process for Nanite meshes:

`// After the subject actor’s resources have streamed in and the subject actor is has finished spawning
for (UPrimitiveComponent* PrimitiveComponent : SubjectPrimitiveComponents)
{
// Force static meshs components to LOD0
if (UStaticMeshComponent* StaticMeshComponent = Cast(PrimitiveComponent))
{
StaticMeshComponent->SetForcedLodModel(1);
}

// Force streamable render assets mip levels to resident
FStreamingTextureLevelContext LevelContext(EMaterialQualityLevel::Num, PrimitiveComponent);
TArray RenderAssetInfoArray;
PrimitiveComponent->GetStreamingRenderAssetInfo(LevelContext, RenderAssetInfoArray);
for (const FStreamingRenderAssetPrimitiveInfo& RenderAssetInfo : RenderAssetInfoArray)
{
RenderAssetInfo.RenderAsset->SetForceMipLevelsToBeResident(30.0f); // 30 seconds should be more than enough for the capture
RenderAssetInfo.RenderAsset->bIgnoreStreamingMipBias = 1;
IStreamingManager::Get().GetRenderAssetStreamingManager().FastForceFullyResident(RenderAssetInfo.RenderAsset);
}
}

// Wait for render assets to stream in
for (UStreamableRenderAsset* RenderAsset : RenderAssets)
{
if (!RenderAsset->IsFullyStreamedIn())
{
return;
}
}

// Pre-warm Nanite resources for a number of frames before the capture
ENQUEUE_RENDER_COMMAND(PreWarmNaniteForThumbnailCapture)
([NaniteResources = MoveTemp(NaniteResources), NanitePreWarmFrameCount = NanitePreWarmFrameCount](FRHICommandListImmediate& RHICmdList) {
IRendererModule& RendererModule = GetRendererModule();
for (const Nanite::FResources* NaniteResource : NaniteResources)
{
RendererModule.PrefetchNaniteResource(NaniteResource, NanitePreWarmFrameCount);
}
});

// Wait for the nanite pre-warm to complete
if (GFrameCounter - NanitePreWarmStartFrame < NanitePreWarmFrameCount)
{
return;
}

// Render the subject repeatedly for a number of frames
if (CaptureFramesRemaining > 0)
{
SceneCaptureComponent->CaptureScene();
–CaptureFramesRemaining;
return;
}`

I’ve experimented with various pre-warm/capture durations and found that 5 frames for each produces decent results, but while the quality is 90% there, 10% of the time the quality deviates, and parts of the Nanite meshes appear notably blurry/low detail.

What I am hoping for is a consistent way to request the highest level of detail for a Nanite mesh, and a definitive way of knowing when the Nanite mesh is fully loaded at that highest level so that the capture can be executed.

Does anyone have any advice or recommendations?

Thanks!

Hello,

Thank you for reaching out.

I’ve been assigned this issue, and we will be looking into this use-case of Nanite streaming for you.

Hello,

You are already rendering your thumbnails in the recommended way.

This ticket discusses “PrefetchNaniteResources(…)”, and some of it’s suggestions might help your use-case:

[Content removed]

A quick summary of ideas from that ticket:

Increasing the “MinimalResicency” on the problematic meshes, if you have the memory budget

Increasing “r.Nanite.Streaming.MaxPendingPages” and/or “r.Nanite.Streaming.MaxPageInstallsPerFrame”, if you have the performance budget

Experimentally increasing “MAX_RESOURCE_PREFETCH_PAGES”

This last suggestion from the ticket involves making engine modifications. For engine modifications like this, we can offer information about existing functionality, and we leave the details of the implementation to you.

Please let us know if this helps.

Thank you for looking into this! I hadn’t seen Dominic’s thread, that was very useful to read.

Unfortunately I don’t think that we will be able to use the ideas that have been suggested due to runtime performance limitations, but I’m glad to hear that we are handling thumbnail rendering in the recommended way.

I hope that one day we will have some form of async call back to help with this situation, but for now we will work with what we have.

Thanks for the help!

Hello,

Thank you for the reply.

Can we close your case? You can always re-open it if you need additional assistance with the same issue.