Level of Detail for textures?

I will be implementing an LOD system so that distant objects and road sections will build with few polygons. Is there any point in reducing Texture Map resolutions? If it reuses the image for all references to it, distant roads aren’t saving anything to load a lower resolution copy of the texture assuming that texture is loaded in higher res for nearby roads?

I made a road texture from a drone photo of a road near me and it looks great at higher resolution, just hoping there isn’t really a cost for that beyond just loading the image once?

Indeed there’s no gain from providing lower-resolution alternative texture versions for far-away polygons. It would actually be detrimental: it’s better if more things use the same texture resources, so better if both the close and far polygons of the road use the same texture.

There are however two techniques, a bit related to your question, that could help quality in these situations:

  • Provide textures with mipmaps, in DDS or KTX formats. See Texturing component | Castle Game Engine , Texturing component | Castle Game Engine .

    What this really means: “mipmaps” ( Mipmap - Wikipedia ) are precalculated lower-resolution texture versions, that are “natively” supported on GPU. I.e. we load to GPU a “pyramid” of images (256x256 version, 128x128 version, 64x64 version…) and GPU will automatically query the best (or 2 best ones, and interpolate). This makes far away objects look really nice, less blurry.

    This “pyramid of images” is still one texture resource on GPU. So GPU is efficient in using it, and using different “mipmap level” (this is effectively “texture LOD”) at each pixel.

    By default CGE actually generates and uses mipmaps automatically for textures. But it uses fast algorithms to doi it. Generating mipmaps yourself, by e.g. GIMP, and storing them in DDS / KTX files, may make the quality of them better.

  • Moreover, you can activate “anisotropic filtering”.

    Right now it requires a bit of code, sample in examples/viewport_and_scenes/anisotropic_filtering/anisotropic_filtering.dpr, you basically copy and adapt the SetAnisotropicFiltering utility from this example. (I’d like to have it more clickable in the future, this is part of roadmap Roadmap | Manual | Castle Game Engine ).

    Note that increasing “anisotropic filtering”, while good for quality, may lower performance. So don’t go too wild, and don’t activate it on all textures. But in practice… this is a technique done by GPUs, and they are ridiculously good at it :slight_smile:

Both these techniques will make polygons seen from far-away have better quality.

1 Like

The texture as shown in the image I posted is 326x326 which is what the original image’s resolution for that area in the drone photo. Sounds like I should at least make that a power of 2 like 256x256?

The engine automatically resizes the texture to power-of-2, so it is actually 512x512 when you see it. You should see a warning about it in the logs.

I still hesitate whether CGE should do it – i.e. resizing your textures automatically if they are not power-of-2. It necessarily means you loose quality. But then, OTOH, resizing the texture to power-of-2 is necessary to generate mipmaps for it, which in turn is necessary to make this texture look good in 3D under any view. So, overall, maybe it was a good decision to “resize to power of 2 by default” because the gains are bigger than drawbacks.

Note: You can of course disable this resizing, set GuiTexture field of TImageTextureNode to true. See Texturing component - extensions | Castle Game Engine . But be prepared then that it implies “no mipmaps possible when not power of 2”.

Also note: We don’t do this automatic resizing for all images in CGE. Using TCastleImageControl, which 2D UI control with image, never resizes to power of 2 – because there’s no need to, it’s a UI image, mipmaps are not useful there. Using TCastleImageTransform also by default doesn’t resize, but you can make it resize by activating TCastleImageTransform.Mipmaps ( Castle Game Engine: CastleScene: Class TCastleImageTransform ).

Long story short: while we resize your 326x326 to 512x512 automatically, it is much better if you do it manually. E.g. GIMP has much better quality resizing algorithms then CGE. And then think about previous ideas – explicit mipmaps, anisotropic filtering.

1 Like

I approve of the engine sizing the textures automatically by default if they aren’t power of two. I sized it to 256x256.

1 Like