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 or supported online providers. Poly Haven is supported out of the box.
Features
- Import PBR texture sets as CS2 materials
- Import
.blend,.glb,.gltf,.fbx, and.objmodels - Import
.hdrand.exrpanoramas as HDR skies - Search and import assets directly from Poly Haven
- 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
cs2assetdirectories
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 --python 3.12 cs2asset --help
Python 3.12 is selected explicitly because cs2asset supports Python 3.12 and 3.13.
Check that cs2asset can find CS2, Valve's tools, Blender, and your addons:
uvx --python 3.12 cs2asset doctor
Then select the addon you want to import assets into:
uvx --python 3.12 cs2asset init
init remembers the selected addon for future commands.
Create new addons through CS2 Workshop Tools before selecting them in cs2asset.
Quick start
Import local assets:
uvx --python 3.12 cs2asset import .\assets\mossy_rock.glb
uvx --python 3.12 cs2asset import .\assets\forest_ground\
uvx --python 3.12 cs2asset import .\assets\sunset.hdr
Or import directly from Poly Haven:
uvx --python 3.12 cs2asset import polyhaven:concrete_floor_01 --resolution 2k
uvx --python 3.12 cs2asset import polyhaven:sunset_jhbcentral --resolution 4k
uvx --python 3.12 cs2asset import polyhaven:dirty_football --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 --python 3.12 cs2asset search "forest ground" --provider polyhaven
uvx --python 3.12 cs2asset search "mossy rock" --provider polyhaven --type models
uvx --python 3.12 cs2asset search "sunset" --provider polyhaven --type hdris
Then import an asset by ID:
uvx --python 3.12 cs2asset import polyhaven:forest_ground_04
uvx --python 3.12 cs2asset import polyhaven:dirty_football
uvx --python 3.12 cs2asset import polyhaven:sunset_jhbcentral
You can also paste a Poly Haven asset URL directly:
uvx --python 3.12 cs2asset import https://polyhaven.com/a/concrete_floor_01
Inspect what will be imported before doing anything:
uvx --python 3.12 cs2asset info polyhaven:concrete_floor_01
Choose a resolution:
uvx --python 3.12 cs2asset import polyhaven:concrete_floor_01 --resolution 1k
uvx --python 3.12 cs2asset import polyhaven:concrete_floor_01 --resolution 2k
uvx --python 3.12 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 --python 3.12 cs2asset list
uvx --python 3.12 cs2asset rebuild IMPORT_ID
Cached Poly Haven assets can also be rebuilt offline:
uvx --python 3.12 cs2asset rebuild IMPORT_ID --offline
Poly Haven 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 |
You can require a specific asset type with:
uvx --python 3.12 cs2asset import SOURCE --type material
uvx --python 3.12 cs2asset import SOURCE --type model
uvx --python 3.12 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 --python 3.12 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 override the format:
uvx --python 3.12 cs2asset import .\rock\ --normal-format dx
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
Supported formats:
.blend
.glb
.gltf
.fbx
.obj
Example:
uvx --python 3.12 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 --python 3.12 cs2asset import .\assets\rock.glb --collision none
A different scale can also be supplied:
uvx --python 3.12 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 --python 3.12 cs2asset import .\assets\sunset.hdr
You can adjust yaw and exposure during import:
uvx --python 3.12 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 --python 3.12 cs2asset projects list
Select one:
uvx --python 3.12 cs2asset projects use de_example
You can also specify the project for an individual import:
uvx --python 3.12 cs2asset import .\assets\rock.glb --project de_example
For scripts or other non-interactive environments:
uvx --python 3.12 cs2asset init --project de_example
Non-interactive commands do not stop to ask for project selection.
Common commands
# Check the local setup
uvx --python 3.12 cs2asset doctor
# Select an addon
uvx --python 3.12 cs2asset init
# Import an asset
uvx --python 3.12 cs2asset import SOURCE
# Inspect an asset
uvx --python 3.12 cs2asset info SOURCE
# Search Poly Haven
uvx --python 3.12 cs2asset search "QUERY" --provider polyhaven
# List installed imports
uvx --python 3.12 cs2asset list
# Rebuild an existing import
uvx --python 3.12 cs2asset rebuild IMPORT_ID
# Show configuration
uvx --python 3.12 cs2asset config show
# Show help
uvx --python 3.12 cs2asset --help
Some useful import options:
uvx --python 3.12 cs2asset import concrete_floor_01 --resolution 1k
uvx --python 3.12 cs2asset import concrete_floor_01 --tiling 2
uvx --python 3.12 cs2asset import concrete_floor_01 --surface concrete
uvx --python 3.12 cs2asset import dirty_football --collision none
uvx --python 3.12 cs2asset import sunset_jhbcentral --yaw 90 --exposure -1
Dry runs
Resolve an import without converting, compiling, or installing anything:
uvx --python 3.12 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 --python 3.12 cs2asset rebuild IMPORT_ID
Local imports normally reread the original source files.
To rebuild from the retained input snapshot instead:
uvx --python 3.12 cs2asset rebuild IMPORT_ID --cached-inputs
Cached provider assets can be rebuilt offline:
uvx --python 3.12 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 --python 3.12 cs2asset blend create `
.\materials\forest_ground `
.\materials\rock `
--name forest_rock
Poly Haven materials:
uvx --python 3.12 cs2asset blend create `
polyhaven:forest_ground_04 `
polyhaven:rock_face_03 `
--name forest_rock
Local and online sources can also be mixed:
uvx --python 3.12 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 --python 3.12 cs2asset config show
Set a user default:
uvx --python 3.12 cs2asset config set resolution 1k
Set a project-specific value:
uvx --python 3.12 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 --python 3.12 cs2asset `
--cs2-root 'D:\SteamLibrary\steamapps\common\Counter-Strike Global Offensive' `
doctor
uvx --python 3.12 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 Blender materials must be baked before importing
- Unsupported or non-standard material graphs may require manual preparation
- Alternate UV channels are not currently supported
- Non-identity texture mapping may 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 --python 3.12 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 --python 3.12 --isolated --from . cs2asset --version
To run the published package without installing a persistent command:
uvx --python 3.12 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 assets are CC0.
Metadata
Release files for cs2asset 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cs2asset-0.2.1.tar.gz | 56.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cs2asset-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 124.8 kB
Release files / cs2asset-0.2.1.tar.gz
| Download URL | cs2asset-0.2.1.tar.gz |
|---|---|
| Size | 56.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
955e1848f36dbf8773ce3cef5e94a0f4802dcac1e966fc9ceee40c8d01497ef8
|
|
BLAKE2b-256 checksum How to use checksums |
1f62626cac1b5001cce557460fb13dcc2cbdc8f5bba520507697a7f8855f61f9
|
| 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 logRelease files / cs2asset-0.2.1-py3-none-any.whl
| Download URL | cs2asset-0.2.1-py3-none-any.whl |
|---|---|
| Size | 68.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8fad4f4b9b5b0f0e3b4d9c9f72712c4516255a0d168bef710443fbfb268c0c8d
|
|
BLAKE2b-256 checksum How to use checksums |
63ecb8b1c1605c564162d55c809401e8dbd5929f33aa8accc6df8257578679be
|
| 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