Mipmaps and quality

[I’m new to mipmapping and there seems to be almost no documentation on how Babylon generates mipmaps, how many and what the costs are. But I gathered from the source code that it just uses an underlying webgl call to do it.]

The generated mipmaps are pretty blurry compared to resizing with an image editor, I will probably create a playground tomorrow to show this.

My questions (I tried to answer the first 2 myself):

  1. is there a way to use a different scaling algorithm for the mipmap generation? (seems like no, based on the webgl call)
  2. what are the costs of the default mipmapping feature? (I suppose it’s just a one-time cost at generation time, I already checked having multiple levels in view does not increase the amout of draw calls)
  3. is there a way to supply custom mipmaps, but keep the nice feature that selecting from which one to sample is still done by the engine?

Thanks as always!
Mise

1/ No, because we call a webgl function to generate the mipmaps, as you noticed.

2/ As you say, generation is a one-off cost, so it shouldn’t matter. However, if you generate custom render target textures and enable mipmaps for these textures, mipmaps will be generated every time (so, probably every frame)! This may not be a problem (mipmap generation should be quite fast), but it’s still extra GPU time that you can save if you don’t enable mipmaps.

3/ There’s currently no way to provide custom mipmaps (@sebavan?), I don’t think, as no one has asked. But if someone is willing to create a PR for it, I think we’re okay with that!

2 Likes

yup correctly you can only do it with a dds or an env file :frowning:

There is nevertheless a function on engine called _uploadImageToTexture which allows uploading the correct mips but it would need a bit of wrapping to be exposed nicely.

3 Likes

That’s clear, thank you both.

some followup questions:

  1. what was the reason for implementing this method? (_uploadImageToTexture)
  2. can it trivially be used for using custom mipmaps if we forget about exposing it for the moment?
  3. I would be worried about still generating the (now unused) default mipmaps, is that correct?

ps:

  • it seems like ThreeJS already has this feature: Custom Mipmaps - Three.js Tutorials
  • I read in more places that the WebGL mipmaps are not of a great quality, but not sure if it’s better on other 3D api’s

I also saw here that WebGPU might not support this generateMipMap function, so it may be needed to implement it in Babylon for this reason, maybe that is relevant in this discussion:

env texture for instance stores the mipmap in a really special way for simulating roughness in PBR materials so we need to be able to load them as we see fit.

In WebGPU @Evgeni_Popov implemented a function to generate the mip map.

This is safely usable on engine but just not exposed at the moment cause it is so niche it is usually associated to a higher level feat like env map, dds, compressed textures… What is your use case ?

the use case is static textures in a 2D view that I want to look as good as possible in different sizes (in a single draw call). I can make an implementation myself, but I would like to reuse as much engine code as possible and would be afraid to hurt performance.

no mipmaps (jagged)

webgl mipmaps (right ones are blurry)

custom mipmaps (manual)

this is the raw texture:

maybe I can reuse part of this, I will take a look at it.

Actually, it’s specific to WebGPU and is simply doing X rendering, each one being half the size of the previous X-1 rendering. It is doing a bilinear filtering to compute the mipmap X from X-1, so I suspect the result is more or less what you get in WebGL when you call the existing mipmap generation function.

In your case, you will probably want to apply a different algorithm when you go from mipmap X-1 to mipmap X.

yeah, exactly. I hope to reuse some of your code, because I don’t have a good grasp of how to tie everything together.

When I’m finished and it’s decent, I will share my work here.

1 Like

I decided to not generate mip-maps in-code, but supply 3 mipmap levels prebaked via images.

Now that you know my use-case, do you have an answer for my questions 2 and 3?

Yes, it seems _uploadImageToTexture can be used to set a mipmap because there’s a lod parameter, which is the mipmap level.

Regarding #3, you can disable the generation of the mipmaps (see the 3rd parameter of the Texture constructor).

1 Like