Source 2 Viewer
Browse VPK archives, view, export, and decompile Source 2 assets, including maps, models, materials, textures, sounds.
Fully open-source and reverse-engineered.
New version released since your last visit — view changelog
Render, inspect, extract, and decompile files from CS2, Dota 2, Deadlock, Half-Life: Alyx, and every other Source 2 game.
Preview any model with its animations, skeleton, and physics.
Open game archives without unpacking them, and extract single files or whole folders.
Animation graphs, Pulse scripts, and map entity I/O drawn as node graphs.
Use the same .NET libraries as Source 2 Viewer in your own projects, or export files from scripts with the command line tool.
Export and decompile Source 2 resources from the command line on Windows, Linux, and macOS.
.NET library that powers Source 2 Viewer (S2V), also known as VRF. This library can be used to open and extract Source 2 resource files programmatically.
// Open package and read a file
using var package = new Package();
package.Read("pak01_dir.vpk");
var packageEntry = package.FindEntry("textures/debug.vtex_c");
package.ReadEntry(packageEntry, out var rawFile);
// Read file as a resource
using var ms = new MemoryStream(rawFile);
using var resource = new Resource();
resource.Read(ms);
Debug.Assert(resource.ResourceType == ResourceType.Texture);
// Get a png from the texture
var texture = (Texture)resource.DataBlock;
using var bitmap = texture.GenerateBitmap();
var png = TextureExtract.ToPngImage(bitmap);
File.WriteAllBytes("image.png", png);
This release adds support for files from the latest CS2 and Deadlock updates.
R8_UNORM texturesRenders a heatmap of triangle overdraw using the same shader as the Source2 tools, accurate to the game and can be used for optimising maps.
Map and model viewers now play sound. vsndevts events are mixed on their own thread with distance volume curves, stereo panning and per-mix-group levels.
New "Debug Performance" option showing general renderer stats, allocations and timings.
This (especially stats) can be used as an analogue for real source2 rendering to some degree in order to help optimise maps, things like total drawcalls, materials, etc are accurate.
CS2 environment materials render their wet weather state, with puddles, a wetness sheen, scrolling wave normals and procedural rain splashes.
Entity lumps and maps now have an entity I/O graph tab, drawing every entity as a node with its Hammer editor icon and every connection as a labelled wire. Nodes link with the 3D viewer.
Pulse graphs are rebuilt from their compiled bytecode back into readable node graphs, and AnimGraph 1 graphs draw alongside them, both compiled and straight out of the editor. Every graph viewer shares one canvas with panning, zooming, search, filtering, island focus and image export.
Mirrors CS2's Baked bomb damage debug view, drawn as animated arrows pointing along the blast direction, coloured from green where a blast is lethal through to red where it is harmless.
Meshes decompiled into Hammer meshes are no longer a wall of triangles: adjacent triangles sharing a material are merged back into quads.
point_template spawn wires and two-way navigation with the map viewerbaked_bomb_damage.vdata_c filesvsnap) viewer.txt dump when extracting those soundsenv_soundscape, snd_soundscape, point_soundevent and snd_event_pointLightTiles, EnvmapTiles and Subgroups debug modesQuadOverdraw debug render mode painting overdraw as a heat mappbr.vfx, environment_blend.vfx and citadel_overlay.vfx materialslight_omni, light_spot and light_ortho entities used by Half-Life: Alyx and SteamVR Homelight_rect area lightsfadetimepath_particle_rope cablesparticles_listenv_particle_glow entity and particle sound events through C_OP_RenderSoundvnmclip)point_template children with their templateSpriteCardTextureChannel_t channel masks and all seven blend modes in the sprite shaderF_USE_NEW_BLENDING height band blend for CS2 csgo_environment_blend materialsbhop, surf, kz and dr mapsMultiply falling through to the additive blend function, and gave ModThenAdd its ownpow(0, 0) in fog, vignette and levels adjustmentlight_environment producing NaN sun shadow matricesenv_sky ignoring its brightnessscalerenderamt above 255 wrapping aroundvnmclip) playing back too fastplayerclip hulls blocking ray traces--game argument pointing at a gameinfo.gi file, so assets outside the game folder resolve--output to write to the exact filename given for a single --vpk_filepath match--stats on VPKs skipping .vcs, .nav, .vfe, .vfont and .uifont entries--vpk_list silently extracting when combined with --output, which is now an error--gltf_compose_additivevnmclip float curvesValveResourceFormat.Renderer.EntitiesEntityLump.Connection and EntityIOTargetResolverAnimationGraphLoader, AnimGraphModelInfo and SkeletonRetargetervdata parsing in the new ValveResourceFormat.ResourceTypes.GenericData namespacePathParticleRopeParticleField and the ParticleDetailLevel enumModelLodInfo describing a model's LOD levels and switch distancesnavmeshcustomdata1, modeldoc41 and vpcf66 KV3 format idsMSLT meshlet block, Texture.RadianceCoefficients and the remaining texture metadataShaderRegistry for mounting your own shader directoriespoint_template children into a single entitylight_environment sun pointing the wrong way in glTF exportsvnmclip clips coming out rotatedInteger64 entity properties printing as huge positive numbersclamp(x, 0, 1) to saturate(x) rewrite almost never firing in decompiled shader sourceAnimation split into SequenceAnimation and ClipAnimation, with playback through one AnimationPlayer per skeletonCamera speaks Source QAngles, and its pitch now measures positive downwardsValveResourceFormat.Utils.GraphLayout was removed outright, with no public replacementEntityTransformHelper methods were renamed after what they returnRenderer.EnableBarnLights replaces the ViewConstants.ExperimentalLightsEnabled fieldImageFormat enum, removing Framebuffer.Stencil and the attachment format recordsVertexInputLayout API, removing DrawCall.VertexArrayObjectRenderMaterial owns MaterialInputs<T>, removing DepthOnlyProgram and collapsing Shader.SetUniform1-4IFileLoader now requires GetFileStreamAvailable on CS2 maps, walk mode now renders the CS2 first-person viewmodel alongside first-person legs, with weapon and leg animations driven by a new animation mixer. Includes multi-dimensional blend spaces, additive breathing, bone masks, muzzle flash, and perspective correction.
Added decompilation of AnimGraph 2 (NmGraph) files back to editable source documents, covering node specifications, type definitions, variations, and virtual parameter types. Round-trip fidelity is preserved across global transitions and animgraph variation overrides.
targetnamevr_unlit into its own shader, mainly for SteamVR Homevr_standardF_TRANSMISSIVE_BACKFACE_NDOTL for three-layer parallax materials.vnmclip filesShaderExtractRsComparison, RsFilter, and RsTextureAddressMode enums, and fixed binding offsets for older shaders (Half-Life: Alyx)VfxRegisterType enum coverage with renamed and added membersVoxelVisibilityName to Skeletonnmclip decompile coordinate system, nmskel root_motion axis, and nmclip glTF export to include the armaturePhysicsHullFile missing the parent_bone propertyThe file explorer now supports a thumbnail grid view with live-rendered previews of models, materials, and textures. Toggle between list and grid layouts, and resize thumbnails with Ctrl+Mouse wheel or the slider. Thumbnails are rendered on a background thread using the full OpenGL pipeline.

Added rendering of barn (cone-shaped) and omni2 (point) lights. Barn lights support perspective and orthographic projection, cookie textures, soft edge falloff, and dynamic shadows.
| Before | After |
|---|---|
![]() |
![]() |
Scene rendering now uses a GPU-driven culling pipeline. A compute shader tests every meshlet AABB against the camera frustum, a hierarchical depth pyramid
(occlusion culling), and a screen-size threshold. This reduces draw overhead in large scenes. Meshlet level culling is available on most Source 2 maps built 2023 and forward.
Added support for parsing .vvis files and visualizing the clusters.

AG2 animation clips can now be played back directly in the model viewer. Clips are loaded from referenced .vnmclip files, organized by folder name alongside AG1 animations.
Decompilation of AnimGraph 1 state machines now covers 35+ node types. State machine condition scripts, virtual parameters, and proper node connection mapping are also supported.
BREAKING: KV3TextSerializer, KeyValues3, KVObject, KVValue have been removed from this library.
KV3 parsing is now powered by ValveKeyValue.
BREAKING: Entity now extends KVObject from ValveKeyValue, and Entity.GetPropertyUnchecked has been removed.
MurmurHash2.Hash to be case-insensitive, with HashCaseSensitive added for the previous behaviorMurmurHash2.Hash version that accepts a single uintGetUnsignedIntegerProperty on negative integers (e.g. SteamVR Home m_nDefaultMeshGroupMask)The rendering engine has been extracted into a separate Renderer project, now published as a standalone NuGet package. This enables external applications to leverage all of our Source 2 rendering capabilities. See Misc/RenderTest for an example project.
Implemented bloom and depth of field post-processing effects.
| Bloom (New) | No Bloom |
|---|---|
![]() |
![]() |
| Depth of Field | Depth of Field |
|---|---|
![]() |
![]() |
Compiled maps include a colored representation of the light map, and now it can be viewed directly using the IrradianceDebug render mode.

We have added a basic experimental first-person movement controls with world geometry collision support. It is roughly based on Counter-Strike movement, but is not exactly the same.
If you are a movement enjoyer, help us polish and improve this new system.
.slang (.frag.slang, .vert.slang)--gltf_mesh_list parameter to filter out unwanted meshes during exportSource 2 Viewer is open-source and built by volunteers. Every contribution helps make it better for everyone.