No description
  • C 73.1%
  • C++ 25.7%
  • Python 0.4%
  • Batchfile 0.3%
  • GLSL 0.3%
  • Other 0.2%
Find a file
dexxdbg 4c38fb2eb8 Infinite far plane + box-shaped skybox tagging
- Camera::perspective_inf: zfar -> infinity projection, so geometry
  never pops out of existence with distance (the x16 skybox terrain
  reaches ~130k units; the old 65536 far plane was visibly clipping
  it). Near plane still maps to -1; sky detection at depth 1.0 keeps
  working since real geometry converges strictly below it. Gate test
  pins the projection math.
- 3D skybox tagging is now a box around sky_camera (16384 wide, 5120
  tall) instead of an 8192 sphere - the sphere missed the sprawling
  hill displacements, leaving pieces of the miniature room floating
  in the real sky.

924 checks pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 15:59:10 +03:00
include Infinite far plane + box-shaped skybox tagging 2026-07-10 15:59:10 +03:00
shaders Sky-cubemap reflections on glass in the translucent pass 2026-07-10 14:48:32 +03:00
src Infinite far plane + box-shaped skybox tagging 2026-07-10 15:59:10 +03:00
tests Infinite far plane + box-shaped skybox tagging 2026-07-10 15:59:10 +03:00
.gitignore Fix all parser/renderer bugs, add gate tests, scan all VPKs 2026-07-10 03:24:55 +03:00
build.bat Add VMF map support: parser, brush clipping, displacements 2026-07-10 14:12:26 +03:00
build.sh Add VMF map support: parser, brush clipping, displacements 2026-07-10 14:12:26 +03:00
README.md Add VMF map support: parser, brush clipping, displacements 2026-07-10 14:12:26 +03:00
run_tests.bat Add VMF map support: parser, brush clipping, displacements 2026-07-10 14:12:26 +03:00
run_tests.sh Add VMF map support: parser, brush clipping, displacements 2026-07-10 14:12:26 +03:00
setup_deps.py init commit of bsp-viewer very buggy dont use 2026-06-14 00:55:06 +03:00

bsp-viewer

A Source engine BSP and VMF map viewer written in C++ with OpenGL 3.3.

PRs are welcomed.

What it is

Parses and renders .bsp map files from Source engine games (Half-Life 2, CS:GO, etc.) and .vmf Hammer/decompiled map sources. Mounts every VPK archive found under the game folder for textures, resolves VMT materials (including patch include chains), decodes VTF textures (7.07.5, DXT1/3/5

  • uncompressed formats), renders lightmapped world geometry, and loads static props (MDL/VVD/VTX, up to MDL v49).

For .vmf maps the brush solids are rebuilt from their half-space planes (huge base quad clipped against every other side), displacement terrain is generated from dispinfo grids (power 24, offsets/elevation included), func_detail/brush-entity solids render too, and face UVs come from uaxis/vaxis (texel scale resolved against the real VTF texture size). VMF has no lightmaps, so VMF maps render fullbright until real-time lighting lands.

What it uses

  • OpenGL 3.3 Core Profile via GLAD
  • GLFW3 for windowing and input
  • stb_image for image loading
  • C++20

Building

Prerequisites

  1. MSYS2/MinGW-w64 with GCC (ucrt64 and mingw64 are auto-detected)
  2. Run setup_deps.py once to fetch GLAD and stb_image headers
  3. Install GLFW:
    pacman -S mingw-w64-ucrt-x86_64-glfw    # MSYS2 ucrt64
    pacman -S mingw-w64-x86_64-glfw         # MSYS2 mingw64
    

Compile

build.bat

Or on Linux/Mac:

./build.sh

The Windows build links -static, so the resulting bsp_viewer.exe has no DLL dependencies.

Tests

run_tests.bat

(./run_tests.sh on Linux/Mac.) Builds and runs the gate test suite in tests/test_parsers.cpp: 230+ deterministic checks against synthetic BSP, VPK, VTF, VMT, and MDL/VVD/VTX fixtures built in memory — no GL context or game assets needed, runs in well under a second. Every previously fixed format bug (LDR/HDR lightmap pairing, sprp v10 stride, VTF 7.3+ resource offsets, VTX v49 strip-group stride, VPK dir-embedded offsets, the camera view matrix, prop model matrices, ...) is pinned by a test.

Usage

bsp_viewer.exe <map.bsp|map.vmf> [game_dir]

game_dir is the game folder; it is scanned recursively and all dir VPKs found are mounted (pak01_dir.vpk, hl2_textures_dir.vpk, ...), so both the flat CS:GO layout and the multi-VPK HL2 layout work. Loose materials/ files on disk are used as fallback. For .vmf maps game_dir defaults to the map's own folder (decompiles usually sit next to loose materials/ + models/). Examples:

bsp_viewer.exe d1_canals_01.bsp "C:\Steam\steamapps\common\Half-Life 2"
bsp_viewer.exe de_dust2.bsp "C:\Steam\steamapps\common\Counter-Strike Global Offensive\game\csgo"
bsp_viewer.exe gm_construct.vmf

Controls

Input Action
W A S D Move
Mouse Look
Space / E Move up
Ctrl / Q Move down
Shift 3x speed boost
[ / ] Halve / double speed
Scroll wheel Adjust speed
Escape Toggle mouse capture

Current state

Working: world geometry with gamma-correct lightmaps, texture loading from VPK/disk (VMT → VTF, patch materials), static props with correct placement/orientation, skybox, HL2 and CS:GO era formats.

Known limitations:

  • Specialty materials (water, 2-way blends $basetexture2, refractive glass) render with their base texture or a gray fallback
  • Displacements (terrain) are not rendered
  • Source skybox face orientation is approximate
  • No BSP visibility culling — the whole map draws every frame (fine on any modern GPU for Source 1 maps)

Source files

File Purpose
src/main.cpp Entry point, GLFW setup, VPK discovery, main loop
src/bsp_parser.cpp Source BSP file parser
src/vmf_parser.cpp VMF (Hammer) parser: KeyValues, brush clipping, displacements
src/renderer.cpp OpenGL rendering, texture/material pipeline
src/vpk_reader.cpp VPK archive reader (multi-archive)
src/vmt_parser.cpp VMT material parser
src/vtf_reader.cpp VTF texture reader
src/mdl_loader.cpp MDL/VVD/VTX model loader
src/glad.c OpenGL loader
tests/test_parsers.cpp Gate test suite (synthetic fixtures)