A complete yet minimal implementation of virtual texturing that is cross-platform and provides a reference sample app.
Virtual texturing is a technique for viewing textures which are larger than can fit in memory. These mega textures are mipmapped and each mipmap level is tiled. Each tile (also called a page) is stored on disk as a separate image file. Tiles are then loaded on-demand based on the current view. Rendering tiles is done in the main thread, with loading and decompressing of pages done asynchronously on one or two background threads, leading to smooth panning and zooming of these big textures.
This work is an OpenGLES-specific and modernized fork of LibVT plus a cross-platform sample app. Special thanks to Julian Mayer for his original implementation and thorough documentation.
Goals:
-
Provide a minimal example of virtual texturing to help in learning the algorithm and to serve as a building block for other projects.
-
Enable cross platform native builds on Mac, Windows, and Linux, and a future WebGL build via Emscripten. To this end, C++ and OpenGLES were chosen from the start.
-
Supply a reference sample that demonstrates the LibVT calls necessary to load and render a virtual texture, while utilizing SDL for cross-platform windowing and event handling.
The sample shows rendering of a test virtual texture to a simple quad. A traditional static texture is also drawn underneath to show how to mix regular rendering with LibVT rendering.
Controls:
Zoom: Mouse wheel
Pan: Arrow keys
Orbit: Left mouse button drag
Reset: 'R' key
Quit: 'ESC' key
Install dependencies for your platform.
Install Homebrew if you don't have it, then SDL2 and SDL2_image:
brew install SDL2
brew install SDL2_image
Build and run:
git clone https://github.com/erik-larsen/hello-vt.git
cd hello-vt
make
cd Sample
./bin-mac-x86_64/hello-vt
or
./bin-mac-arm64/hello-vt
depending on your Mac.
Setup clang compilation on Windows. First, install MSYS from cmd.exe:
winget install MSYS2.MSYS2
setx PATH "%PATH%C:\msys64\clang64\bin"
Then run from MSYS2 CLANG64 shell:
pacman -Syu
pacman -S git
pacman -S base-devel mingw-w64-clang-x86_64-toolchain
pacman -S mingw-w64-clang-x86_64-SDL2
pacman -S mingw-w64-clang-x86_64-SDL2_image
Then to build and run (also from MSYS2 CLANG64 shell):
git clone https://github.com/erik-larsen/hello-vt.git
cd hello-vt
make
cd Sample
./bin-win-x86_64/hello-vt.exe
This was tested on Debian 11.3 and Ubuntu 24.04:
sudo apt update
sudo apt install git
sudo apt install build-essential clang
sudo apt install libsdl2-dev libsdl2-image-dev
Then to build and run:
git clone https://github.com/erik-larsen/hello-vt.git
cd hello-vt
make
cd Sample
./bin-linux-x86_64/hello-vt
Many virtual texturing implementations have been available in C, C++ and JS, using OpenGL, Direct3D, and WebGL. However, for the purposes of this project they are either not well-documented, not minimal, not cross-platform, or not straightforward to build due to age (most date from 2010 or earlier). Of note, OpenSeaDragon is an excellent implementation of virtual texturing but is not a good fit for this project because it is not C++ and not minimal.
Instead, LibVT was chosen for its C++ implementation, OpenGLES code path, and decent documentation. Fixes were made to LibVT to get it running again 15 years later, and to remove code not on the OpenGLES code path. Further, an SDL-based sample app with a pre-processed test image is provided to demonstrate LibVT. (Note: At one time LibVT provided its own pre-built sample, but the link is dead and not saved on archive.org).
For an overview of LibVT's multithreading implementation, see the LibVT readme.
- Code minimized to OpenGLES2 / WebGL1
- Synchronous framebuffer readback
- Decompress png/jpg files only, using stb
- No texture compression
- Multithreading (main, loader, and decompression threads)
- PNG sample
- JPG sample
- Emscripten build, with tiles from server
- Visualize virtual and physical textures for debugging
- Auto configure LibVT based on input image
- Add OpenGLES3 / WebGL2 code path
- Async + double-buffered PBO readback
- ETC2 GPU texture compression (guaranteed in WebGL2)
- Anisotropic texture filtering (via GL_EXT_texture_filter_anisotropic)
- Maybe use faster, browser-standard decompression libs, libjpeg-turbo and libpng
- Maybe handle more image tile formats (any requests?)
- Erik Larsen (LibVT fork and sample app)
- Julian Mayer (original LibVT author)