Skip to main content

cs2asset

Import textures, HDR skies, and 3D models into Counter-Strike 2 Hammer.

cs2asset converts common asset formats into Source 2 resources, runs Valve's compiler, and installs the result directly into a selected CS2 addon.

Assets can come from local files, Poly Haven, or ambientCG. Poly Haven supports materials, HDR skies, and models; ambientCG supports PBR materials.

Features

  • Import PBR texture sets as CS2 materials
  • Import .blend, .glb, .gltf, .fbx, and .obj models
  • Import .hdr and .exr panoramas as HDR skies
  • Search and import assets directly from Poly Haven and ambientCG
  • Generate editable Source 2 source files and compiled resources
  • Automatically discover CS2 Workshop Tools, Blender, and addon projects
  • Rebuild previously imported assets without changing their Hammer paths
  • Create experimental two-layer environment blend materials
  • Keep generated assets organized in dedicated cs2asset directories

Setup

You'll need Counter-Strike 2 with Workshop Tools installed and Blender.

Blender is used internally for conversion and inspection, including the model pipeline and other asset-processing tasks.

The examples in this README use uv, but cs2asset is a normal Python package and does not depend on uv specifically.

Run the published package directly without cloning this repository:

uvx cs2asset --help

Check that cs2asset can find CS2, Valve's tools, Blender, and your addons:

uvx cs2asset doctor

Then select the addon you want to import assets into:

uvx cs2asset init

init remembers the selected addon for future commands.

Create new addons through CS2 Workshop Tools before selecting them in cs2asset.

Quick start

Windows right-click import

Register Import into CS2 Hammer for supported model files, HDR/EXR skies, and PBR texture ZIP archives:

uvx cs2asset context-menu add
uvx cs2asset context-menu status
uvx cs2asset context-menu remove

Registration applies only to your Windows user and does not require administrator access or change default file associations. On Windows 11, use Show more options. Select one file at a time. The importer uses your saved addon, or prompts you to choose one, and keeps the console open until you press Enter after the import.

The entry uses an absolute path to uv.exe to run the published cs2asset package, not a temporary Python environment. If uv is not on PATH, use context-menu add --uv "C:\path\to\uv.exe". Run add again if you move uv. When testing an unreleased checkout, Explorer still runs the published package; the published version must include these commands before the entry can be used.

Import local assets:

uvx cs2asset import .\assets\mossy_rock.glb
uvx cs2asset import .\assets\forest_ground\
uvx cs2asset import .\assets\sunset.hdr

Or import directly from Poly Haven:

uvx cs2asset import polyhaven:concrete_floor_01 --resolution 2k
uvx cs2asset import polyhaven:sunset_jhbcentral --resolution 4k
uvx cs2asset import polyhaven:dirty_football --resolution 2k

Or import a material directly from ambientCG:

uvx cs2asset import ambientcg:Grass005 --resolution 2k

After an import, cs2asset prints the final Source 2 resource path. Use that path directly in Hammer's Asset Browser.

An already-open Hammer session may need an Asset Browser refresh before newly imported resources appear.

Using Poly Haven

Poly Haven is the easiest way to get usable materials, HDRIs, and models into Hammer without manually downloading and converting files.

Search for assets from the CLI:

uvx cs2asset search "forest ground" --provider polyhaven
uvx cs2asset search "mossy rock" --provider polyhaven --type models
uvx cs2asset search "sunset" --provider polyhaven --type hdris

Then import an asset by ID:

uvx cs2asset import polyhaven:forest_ground_04
uvx cs2asset import polyhaven:dirty_football
uvx cs2asset import polyhaven:sunset_jhbcentral

You can also paste a Poly Haven asset URL directly:

uvx cs2asset import https://polyhaven.com/a/concrete_floor_01

Inspect what will be imported before doing anything:

uvx cs2asset info polyhaven:concrete_floor_01

Choose a resolution:

uvx cs2asset import polyhaven:concrete_floor_01 --resolution 1k
uvx cs2asset import polyhaven:concrete_floor_01 --resolution 2k
uvx cs2asset import polyhaven:sunset_jhbcentral --resolution 4k

Default Poly Haven resolutions are:

  • 2K for textures
  • 2K for models
  • 4K for HDR skies

If a requested resolution does not exist, cs2asset reports the available choices.

Once imported, the asset behaves like any other local cs2asset import and can be listed or rebuilt:

uvx cs2asset list
uvx cs2asset rebuild IMPORT_ID

Cached Poly Haven assets can also be rebuilt offline:

uvx cs2asset rebuild IMPORT_ID --offline

Poly Haven assets are CC0.

Using ambientCG

ambientCG provides PBR materials that can be downloaded and imported directly into Hammer.

Search for materials from the CLI:

uvx cs2asset search "grass" --provider ambientcg

Then import a material by ID:

uvx cs2asset import ambientcg:Grass005

You can also paste an ambientCG asset URL directly:

uvx cs2asset import https://ambientcg.com/a/Grass005

Inspect the selected download before importing:

uvx cs2asset info ambientcg:Grass005

Choose a resolution:

uvx cs2asset import ambientcg:Grass005 --resolution 1k
uvx cs2asset import ambientcg:Grass005 --resolution 2k

The default resolution is 2K. The importer prefers PNG packages and falls back to JPG at the requested resolution. If that resolution is unavailable, it reports the available packages.

Once imported, materials can be listed and rebuilt like other imports:

uvx cs2asset list
uvx cs2asset rebuild IMPORT_ID

Cached ambientCG materials can also be rebuilt offline:

uvx cs2asset rebuild IMPORT_ID --offline

Use the ambientcg: prefix or an ambientCG asset URL; bare asset IDs default to Poly Haven. ambientCG support currently covers materials.

ambientCG assets are CC0.

Supported inputs

cs2asset normally detects the asset type automatically.

Input Imported as
.blend Model
.glb Model
.gltf Model
.fbx Model
.obj Model
.hdr HDR sky
.exr HDR sky
Texture directory Material
Texture ZIP Material
polyhaven:ID Poly Haven asset
Poly Haven asset URL Poly Haven asset
ambientcg:ID ambientCG material
ambientCG asset URL ambientCG material

You can require a specific asset type with:

uvx cs2asset import SOURCE --type material
uvx cs2asset import SOURCE --type model
uvx cs2asset import SOURCE --type sky

Materials

A directory containing a recognizable PBR texture set can be imported directly.

For example:

rock/
├── rock_albedo.png
├── rock_normal.png
├── rock_roughness.png
└── rock_ao.png

Import it with:

uvx cs2asset import .\rock\

Supported texture names include:

Map Common names
Base color basecolor, base_color, albedo, diffuse, color, diff
Normal normal, normalgl, normaldx, nor_gl, nor_dx, nrm
Roughness roughness, rough
Metalness metallic, metalness, metal
Ambient occlusion ao, ambient_occlusion
Height height, displacement, disp
Opacity opacity, alpha
ARM / ORM AO, roughness, and metalness in R/G/B

A base-color texture is required.

Generic names such as normal and nrm are treated as OpenGL normal maps by default. Explicit GL and DirectX names are detected automatically.

You can specify the convention for generic normal filenames:

uvx cs2asset import .\rock\ --normal-format dx

Local folders and ZIP packages can contain both DirectX and OpenGL normal maps for the same material. The importer selects OpenGL when both exist and detects DirectX when it is the only variant. Duplicate maps of one convention and mixed texture sets still produce an ambiguity error. Explicit NormalGL/NormalDX filenames determine conversion; --normal-format dx is a hint for generic normal filenames with no declared convention. Selected normals are reported in choices and warnings, and DirectX inputs are converted to OpenGL once.

Materials use CS2's csgo_complex.vfx shader.

Missing optional maps use constant values rather than preventing the material from being imported.

Packed ARM/ORM maps are supported when their layout is known.

Models

FBX embedded images are extracted into the build workspace. Missing external images are resolved against the model directory and its .fbm folder; ambiguous filenames produce an error. Textures must be connected to supported material shader inputs.

Supported formats:

.blend
.glb
.gltf
.fbx
.obj

Example:

uvx cs2asset import .\assets\mossy_rock.glb

cs2asset uses Blender to inspect and convert the source before generating the Source 2 model resources required by Hammer.

Static meshes, UVs, materials, supplied LODs, and basic collision are supported.

By default, a simple convex collision hull is generated. Collision can be disabled:

uvx cs2asset import .\assets\rock.glb --collision none

A different scale can also be supplied:

uvx cs2asset import .\assets\rock.glb --scale 1.0

Rigged models are currently imported as static snapshots of their evaluated pose.

HDR skies

HDR and EXR panoramas can be imported directly:

uvx cs2asset import .\assets\sunset.hdr

You can adjust yaw and exposure during import:

uvx cs2asset import .\assets\sunset.hdr --yaw 90 --exposure -1

The generated sky material can be assigned to env_sky in Hammer.

The panorama provides the visual sky and environment data. Map-specific lighting such as sun direction and brightness is still configured in Hammer.

Projects

List discovered addons:

uvx cs2asset projects list

Select one:

uvx cs2asset projects use de_example

You can also specify the project for an individual import:

uvx cs2asset import .\assets\rock.glb --project de_example

For scripts or other non-interactive environments:

uvx cs2asset init --project de_example

Non-interactive commands do not stop to ask for project selection.

For the complete command and argument list, see the CLI reference.

Common commands

# Check the local setup
uvx cs2asset doctor

# Select an addon
uvx cs2asset init

# Import an asset
uvx cs2asset import SOURCE

# Inspect an asset
uvx cs2asset info SOURCE

# Search online providers
uvx cs2asset search "QUERY" --provider polyhaven
uvx cs2asset search "QUERY" --provider ambientcg

# List installed imports
uvx cs2asset list

# Rebuild an existing import
uvx cs2asset rebuild IMPORT_ID

# Show configuration
uvx cs2asset config show

# Show help
uvx cs2asset --help

Some useful import options:

uvx cs2asset import concrete_floor_01 --resolution 1k
uvx cs2asset import concrete_floor_01 --tiling 2
uvx cs2asset import concrete_floor_01 --surface concrete
uvx cs2asset import dirty_football --collision none
uvx cs2asset import sunset_jhbcentral --yaw 90 --exposure -1

Dry runs

Resolve an import without converting, compiling, or installing anything:

uvx cs2asset import concrete_floor_01 --dry-run

This is useful for checking the selected source, detected asset type, options, project, and expected output paths.

Rebuilding assets

Previously imported assets can be rebuilt while keeping their existing Hammer resource paths:

uvx cs2asset rebuild IMPORT_ID

Local imports normally reread the original source files.

To rebuild from the retained input snapshot instead:

uvx cs2asset rebuild IMPORT_ID --cached-inputs

Cached provider assets can be rebuilt offline:

uvx cs2asset rebuild IMPORT_ID --offline

Use cs2asset list to find import IDs.

Environment blends

Experimental

cs2asset can create two-layer Hammer materials using csgo_environment_blend.vfx.

Local materials:

uvx cs2asset blend create `
    .\materials\forest_ground `
    .\materials\rock `
    --name forest_rock

Poly Haven materials:

uvx cs2asset blend create `
    polyhaven:forest_ground_04 `
    polyhaven:rock_face_03 `
    --name forest_rock

Local and online sources can also be mixed:

uvx cs2asset blend create `
    .\materials\rock `
    polyhaven:forest_ground_04 `
    --name mixed_ground

The resulting material can be applied to suitable Hammer geometry and painted using Hammer's blend tools.

The current implementation supports two layers. Extra layers, custom transition controls, and cutout/blended transparency are not yet supported.

Configuration

Show the current configuration:

uvx cs2asset config show

Set a user default:

uvx cs2asset config set resolution 1k

Set a project-specific value:

uvx cs2asset config set surface concrete --project de_example

Configuration precedence is:

command line
↓
project configuration
↓
user configuration
↓
automatic discovery

Useful environment variables:

CS2ASSET_CONFIG_DIR
CS2ASSET_CACHE_DIR
CS2ASSET_CS2_ROOT
CS2ASSET_BLENDER

Custom tool locations can also be provided directly:

uvx cs2asset `
    --cs2-root 'D:\SteamLibrary\steamapps\common\Counter-Strike Global Offensive' `
    doctor
uvx cs2asset import dirty_football `
    --blender 'C:\Program Files\Blender Foundation\Blender 5.1\blender.exe'

Generated resources

Editable Source 2 resources are installed into the selected addon's content tree.

Compiled resources are installed into the corresponding game tree.

Generated assets are organized under:

materials/cs2asset/
materials/skybox/cs2asset/
models/cs2asset/

This keeps imported resources separate from manually created addon assets.

Resource filenames use the asset name, so Hammer displays names such as lifebuoy.vmdl, lifebuoy.vmat, and snow_road.vmat instead of model.vmdl or blend.vmat. Provider/asset/variant folders still separate sources and settings. A model with one material puts its named VMAT directly in its material variant folder; several materials use names such as lifebuoy_rope.vmat in separate folders.

Rebuild older imports to get these names. Previously owned generic resource paths remain as editable and compiled compatibility copies, preserving existing map references. New imports do not create these copies. The manifest records them in resource_aliases.

Valve compiler warnings appear in terminal/JSON output and the manifest's combined warnings list. compiler_warnings records each warning's resource, message, and log path. Warnings remain visible after an unchanged dependency check and clear after a clean rebuild.

cs2asset also retains the information needed to rebuild previously imported assets.

Limitations

Current limitations include:

  • Models are imported as static geometry
  • Skeletal animation is not exported
  • Rigged models are imported as static evaluated poses
  • Physics-prop setup is not generated
  • Collision is limited to a simple convex hull
  • Automatic LOD generation is not implemented
  • Procedural Principled material inputs require --bake-materials
  • Unsupported or non-standard material graphs may require manual preparation
  • Multiple UV channels on the same mesh require baking
  • Compatible affine UV mappings are applied to mesh UVs; conflicting mappings require baking
  • Material opacity uses alpha testing rather than blended transparency
  • Displacement/parallax is not currently generated
  • Environment blends are experimental
  • HDR sky imports do not configure map-specific sunlight

Where possible, unsupported inputs result in an explicit conversion error rather than silently generating an incorrect asset.

Development

Clone the repository and install its development dependencies:

uv sync --locked
uv run cs2asset --help

Run the test suite:

uv run pytest -q
uv run ruff check src tests scripts

Run integration tests against locally installed CS2 and Blender tools:

$env:CS2ASSET_INTEGRATION = '1'
uv run pytest -q

Build the package:

uv build

Installation

Install from PyPI with uv:

uv tool install cs2asset

Then use cs2asset directly:

cs2asset doctor
cs2asset init
cs2asset import .\assets\rock.glb

You can also install the package using another Python package manager if preferred.

To run directly from the repository without installing:

uvx --isolated --from . cs2asset --version

To run the published package without installing a persistent command:

uvx cs2asset doctor

To upgrade a persistent installation, run uv tool upgrade cs2asset.

Releases

The .github/workflows/publish.yml workflow tests, builds, and publishes to PyPI when a v* tag is pushed. The tag must match both versions in pyproject.toml and src/cs2asset/__init__.py.

Before the first release, configure a pending Trusted Publisher in your PyPI account with these values:

  • Project name: cs2asset
  • GitHub owner: gronnmann
  • Repository: cs2asset
  • Workflow filename: publish.yml
  • Environment: pypi

For each release, update both package versions, run uv lock, commit the changes, and push the branch and matching tag:

git push origin master
git tag -a v0.2.1 -m "Release 0.2.1"
git push origin v0.2.1

Use the new version number for subsequent releases. PyPI versions cannot be reused.

License

See LICENSE for the license of cs2asset.

Assets imported through cs2asset retain their original licenses. Poly Haven and ambientCG assets are CC0.

Models with multiple objects and mapped materials

One source file produces one model by default. Inspect the source before selecting or splitting it (inspection downloads dependencies but does not compile or install):

cs2asset model-list https://polyhaven.com/a/fir_sapling_medium
cs2asset import trees.blend --object TreeA
cs2asset import trees.blend --collection TreeA
cs2asset import trees.blend --split collections --origin center
cs2asset import props.blend --split objects
cs2asset import trees.blend --bake-materials --bake-resolution 2048

Selection uses exact names. Object selection includes its descendants and matching named LOD siblings. Object splitting starts with visible objects without an LOD suffix or with LOD0. Collection splitting uses top-level scene collections, keeping nested collections and LODs together. Hidden render objects are excluded. Each split group has its own model and material resources, recorded in one import so rebuilding repeats the same selection. Materials are currently generated separately for each split group. --origin source preserves source coordinates; center centers each model's LOD0 bounding box and applies that offset to all its LODs.

Compatible constant Mapping nodes are applied directly to exported UV coordinates. Named UV maps and corner vector UV attributes are supported. Conflicting texture mappings, procedural coordinates, and rotation/reflection with tangent normal maps require explicit baking. --bake-materials bakes linked base color, roughness, metalness, opacity, and tangent normal inputs from a Principled BSDF onto the active UV layout. Resolution accepts 16–8192 pixels. Baking does not unwrap meshes: overlapping UVs must represent compatible surface values, and UV islands must fit the texture tile. A mixed surface with one connected Principled shader can bake that PBR component; additional translucent/additive lobes are omitted and reported. Surfaces without a unique connected Principled shader remain unsupported.

Metadata

Release files for cs2asset 0.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cs2asset 0.3.3
File Size Uploaded
cs2asset-0.3.3.tar.gz 67.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cs2asset 0.3.3
File Interpreter ABI Platform
cs2asset-0.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 147.8 kB

Release files / cs2asset-0.3.3.tar.gz

Download URL cs2asset-0.3.3.tar.gz
Size 67.2 kB
Tags Source
SHA-256 checksum
How to use checksums
9da7da1760de08610b19697a3b21f07e6147d568b3747c73b02418bd3d32001b
BLAKE2b-256 checksum
How to use checksums
c9b1a0c22fe7243c68ed59612002de12c63d1efd310a0000dc93afe8c1306982
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / cs2asset-0.3.3-py3-none-any.whl

Download URL cs2asset-0.3.3-py3-none-any.whl
Size 80.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
77880850c2a1179a5e2378160d9d5205e9267315e533bf159bd9c996c47f969f
BLAKE2b-256 checksum
How to use checksums
24414e2234381ccd415d6ba6d10d391519ce12ff35e75366a7f167313eaf6116
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.5

2 release files

0.3.4

2 release files

This release

0.3.3 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page