Texture Streaming was introduced for the Vulkan API in update 0.37. It lets the engine load texture mip levels on demand instead of keeping every texture at full resolution in memory.
Since update 0.39, Direct3D 12 is also supported and includes texture streaming support.
Texture Streaming is supported only on:
It is not supported on Direct3D 11.
Texture streaming loads texture detail on demand. Instead of keeping every texture at full resolution in VRAM, the renderer tracks which mip levels are needed and requests higher or lower resolution mips as required.
BeamNG uses GPU feedback to determine which mip levels are sampled during rendering. The streaming system prioritizes textures that are visible and close to the camera, while keeping distant or unused textures at lower resolution.
This reduces:
Streamable textures may initially load at a lower mip level. Higher-resolution mips are streamed in later when needed.
Texture streaming uses a VRAM budget to decide when to load or unload high-resolution mip levels.
There is an exception for GPUs with memory budget below 6 GB. On these systems, the engine may continue allowing higher-resolution mips to stream in even near the normal stop threshold, so textures do not stay permanently too blurry on lower-memory hardware.
If the streaming budget is reached, textures may appear blurry or muddy because higher-resolution mip levels are not being loaded. This is intentional: it is better for the game to remain playable than to run out of VRAM.
Texture streaming depends on how quickly texture data can be read from disk.
A slow HDD or SSD can increase the time it takes for high-resolution mip levels to appear. This may cause visible texture pop-in, where textures start blurry and become sharper after a delay.
Fast SSDs improve streaming responsiveness, especially in large levels, with many vehicles, or when moving quickly through the world.
Texture Quality controls the maximum texture resolution used by the renderer.
| Texture Quality | Resolution impact | Example from 4096x4096 |
|---|---|---|
| Normal | Full resolution | 4096x4096 |
| Low | Drops by 1 mip level | 2048x2048 |
| Lowest | Drops by 2 mip levels | 1024x1024 |
Each mip level halves the texture resolution in both width and height.
This means:
Because texture memory scales with total pixel count, dropping one mip level greatly reduces memory usage.
For example:
4096x4096 = 16,777,216 pixels
2048x2048 = 4,194,304 pixels
1024x1024 = 1,048,576 pixels
So dropping from 4096x4096 to 2048x2048 reduces the top mip pixel count to 25% of the original.
Mipmaps are smaller precomputed versions of a texture.
A 4096x4096 texture usually contains a full mip chain:
4096x4096
2048x2048
1024x1024
512x512
256x256
128x128
64x64
32x32
16x16
8x8
4x4
2x2
1x1
The renderer selects the appropriate mip level based on how large the texture appears on screen.
Mipmaps:
Without mipmaps, distant textures may flicker, shimmer, or waste bandwidth by sampling unnecessarily large images.
Power-of-two textures use dimensions such as:
128x128
256x256
512x512
1024x1024
2048x2048
4096x4096
They are recommended because they produce clean mip chains down to 1x1.
Power-of-two textures work better for:
Block-compressed formats such as BC4, BC5, and BC7 also work in fixed-size compression blocks, usually 4x4 pixels. Power-of-two textures avoid padding, alignment issues, and inefficient mip chains.
DDS textures are GPU-ready texture files. They can store compressed formats such as BC7, BC5, and BC4, and they include mipmaps.
Using cooked DDS textures provides:
In BeamNG, source PNG textures should be processed through the Texture Cooker , which creates optimized DDS files.
PNG is useful as an authoring format, but it is not a good runtime GPU texture format.
PNG files are compressed on disk, but GPUs cannot sample PNG data directly. Before use, PNG textures must be decoded into raw pixel data and uploaded or converted into a GPU-friendly format.
This can cause:
For example, a 4096x4096 RGBA PNG may look small on disk, but once decoded it requires:
4096 x 4096 x 4 bytes = ~64 MiB
That is only one texture, before considering additional maps such as normal, roughness, metallic, AO, opacity, and emissive.
By comparison, a cooked DDS using GPU block compression, such as BC7 for color textures, is much more efficient. BC7 uses about 1 byte per pixel, so a 4096x4096 texture with a full mip chain requires roughly:
4096 x 4096 x 4/3 = ~21 MiB
Cooked DDS textures are GPU-ready, include mipmaps, use less VRAM and bandwidth, and work properly with texture streaming and quality settings.
Texture performance is not only about VRAM size. Memory bandwidth also matters.
When rendering a scene, the GPU constantly reads texture data. Large uncompressed textures require more bandwidth, especially when used on large surfaces or sampled many times.
High bandwidth usage can reduce performance because the GPU spends more time waiting for texture data instead of shading pixels.
Watch this especially on:
Mipmaps and GPU compression reduce bandwidth cost by ensuring the GPU reads smaller and more cache-friendly texture data whenever possible.
The Texture Cooker converts correctly named PNG source textures into optimized DDS textures.
Recommended workflow:
*.color.png*.normal.png*.data.pngThe game will automatically use the cooked DDS if it exists.
Materials should reference the PNG path, not the DDS path.
Example:
/vehicles/mycar/body.color.png
Do not manually reference:
/vehicles/mycar/body.color.dds
Material debug tools show which mip levels are being used.
Use:
Material Debug Visualization → Base Color Mip Level
This view shows how much of the original texture resolution is actually being used on screen.
Use this to find:
If a texture almost always appears at lower mip levels, it may not need to be authored at such a high resolution.
Texture streaming, mipmaps, and DDS textures keep texture memory and bandwidth under control.
Author clean source textures, cook them to DDS, use power-of-two resolutions, and verify mip usage with debug tools.
Was this article helpful?