Streamable textures not using desired mips

Here is an exemple :

Facades, ground and tree textures are highest / good enough:

[Image Removed]

Disable streaming on the fly leads to this:

[Image Removed]

Also, as far as I could tell, the pool is far from being full so starvation is not the cause.

Any clue on what could be happening and how to resolve this ?

In another case, we received a hint (GEngine->AddTextureStreamingLoc) and applied it temporarily. It seems to do the job but feels like a workaround and not the proper solution. I would expect the view to be enough as assuming I understood the code, the projection is given to the streaming manager.

Thanks,

[Attachment Removed]

Steps to Reproduce
Hi,

We are simulating, among other things, UAV views using very narrow field of views (down to ~0.1 degrees) and we noticed that enabling texture streaming in the project was leading to poor quality image being rendered on screen.

Based on the visibility range ( >50 kilometers), in order to have high level content on distant location, we are adding extra streaming sources (with regards to world partition).

What are the heuristics for mip selection and how can we ensure we truly see what is needed ?

Thanks,

[Attachment Removed]

Salut Basile,

The original system for deciding which mipmap to load in a texture is very old. IIRC, it’s based on a mesh bounding box and UV density.

I know that when you have strange UV layouts, it can go wrong. And it runs on CPU…

I’m almost sure it’s not taking the Field of View into account, which explains why you see this effect.

The modern way to achieve what you want is to use Virtual Textures. With VT, the required mipmap level is a direct feedback from the GPU, considering the exact screen size.

Of course, indexing a VT is a bit more costly, but not much on modern GPUs, and there are other advantages, such as an improved memory pool.

I checked on one of my projects, with the CVAR r.VT.Borders 1 enabled. It displays the mipmap level using a color scheme.

You can see the FOV is properly considered.

[Image Removed]If I zoom even more, all lines are white, meaning the higher mip level.

Note that when using VT, the r.TextureStreaming 0 flag has no effect on them.

You also need a specific Sampler for VT in your material, and you can mix regular textures and VT in the same material.

I hope it helps

[Attachment Removed]

Hi Alban,

You are quite familiar with our project so if you say that virtual texture is the way to go for us, then we will consider making the switch and will leave with the workaround for now.

Still I have a couple question :

  • Currently, our bottle neck is GPU and we even disable the depth pass (prepass). As far as I understand, this will be pushing more onto the GPU and this will be forcing us to re enable it. Do you know if disabling virtual texture (within command line) is falling back to (streamable) textures or if this will be breaking content compatibility ? Ideally, we would like to build our content so it remains compatible. For instance, following your comment, we figured out how to ensure that nanite fallback mesh is not degraded so we can prepare nanite ready content even if we do not enable it fully yet…
  • I am not sure to fully understand this comment on limitation ( https://dev.epicgames.com/documentation/unreal\-engine/streaming\-virtual\-texturing\-in\-unreal\-engine ) : “UE limits support for anisotropic filtering by the size of the Tile Border setting. The default value of 4 allows for less anisotropic filtering than is typical for textures but increasing this value increases memory usage.”
    • As you know, runway markings and other simulation content will be sensitive to this and I would like to ensure I have a clear understanding.
  • Virtual textures seems build / meant for landscape / large textures. Is there any rule of thumbs to determine if a texture shall be VT / streamable / “traditional” ?

Thanks,

Basile

[Attachment Removed]

Hi Basile,

Unfortunately, switching to VT will break your existing content, since it requires changing the asset type for the Textures and using new VT samplers for the material. And there is no global switch for using/not using VT, because it’s really different shader/sampler sets. VT will push the GPU a bit more, but not by much. Profiling your GPU time will tell you the impact, though not all of them will probably need to be converted.

You can probably make a code change to account for the current FOV in the legacy texture streaming module if you don’t want to use VT.

The comment about the limitation is basically telling you that, because a VT is essentially a texture atlas in memory, we need to slightly dilate the color around each cell to prevent mipmap color bleeding. (like it’s often done in vegetation textures around the alpha limit). Because anisotropic filtering needs proper information, the basic border is 4 pixels, which is a good compromise. So technically speaking, there is more memory usage. But a 4-pixel border on a 1024k texture is not the same percentage increase as a 4-pixel border on a 64k texture. It’s not a huge increase overall.

There is no specific global rule for whether to enable VT. It really depends on your content, your memory pool, and your project.

I’ve heard that enabling VT is usually interesting for resolutions above 1024, but once again, only your project numbers will be the right decision-maker.

In your case, I’ll opt for it at least for the terrain imagery, but probably not for the detail textures.

If you’re already GPU-bound and have done all possible other optimizations, enable them only for the most artifact-critical ones.

[Attachment Removed]