No results found.

Earlier work

CS3D

Started in 2018 as a Chrome extension that put rotatable CS:GO knives on Steam Market listings. Rebuilt in 2026 to paint any CS2 finish, pattern seed and float live in the browser.

Source on GitHub ↗

The CS3D skin viewer showing an AK-47 Asiimov at Minimal Wear, float 0.09, with a finish list, float and pattern seed sliders, sticker, name tag and StatTrak controls, and inspect, first person and third person views
The skin viewer demo of the CS2 rewrite, running locally on 12th August 2026
CS2 finishes in the data
1,388
Renders checked against Valve's icons
2,128
Processing a CS2 update
~12–15 min

Steam Community Market listings for CS:GO knives showed a single flat image of the skin. CS3D started in February 2018 as a Chrome extension that put a 3D model you could rotate in its place.

In August 2026 I rebuilt it for CS2. Instead of showing a model with a fixed texture, it paints the finish itself, so any skin, pattern seed and float can be viewed, embedded in another site or exported as an image.

Why paint the finish in the browser

Skinport, CS.Money and SkinBaron all run 3D skin viewers. Reading their shipped JavaScript on 9th August 2026, all three send a texture painted on their servers for each item, and CS.Money had only pattern seed 0 populated.

CS3D paints the finish on the GPU while you look at it, from the same inputs the game uses: the pattern, its seed, the float and the finish’s colours. Changing the seed or the float is a redraw, not a new server bake. The cost is weight, because the browser has to download the inputs rather than one finished picture, which is what the compression work below is for.

How it works

Everything is derived from CS2’s own game files by a scripted pipeline of 40 stages, which uses Source 2 Viewer (ValveResourceFormat) to decompile them and runs in Docker. Of the 1,388 finishes in the data, 1,076 are procedural (colours and a tiling pattern, composited in the shader) and 312 are fully painted texture sets. One API handles both.

The renderer is three.js, with a WebGL port of the game’s weapon paint shader covering all ten paint styles. The seed places the pattern, wear and grunge the way the game’s random rolls do, and wear was checked against in-game screenshots at Factory New (0.02) and Battle-Scarred (0.46).

To find where it looks wrong, I rendered 2,128 items on 8th August 2026 and compared each with Valve’s own inventory icon, ranked by how far they disagree. The worst offenders get fixed first.

Another site embeds it in one of three ways: an iframe driven by URL parameters and postMessage, a native JavaScript module, or pre-rendered frames from a render server. The iframe and the module share one API:

import { mount } from './js/embed.js';
const cs3d = await mount(document.getElementById('view'));
await cs3d.setState({ weapon: 'ak47', kit: 'cu_ak47_asiimov', seed: 661, wear: 0.09 });

That call is the AK-47 in the screenshot above.

The demos

Four reference integrations run on the same renderer: the skin viewer above, a marketplace, a case opening and a creator studio. The viewer also decodes Steam inspect links in their inline form, which carry the whole item (finish, seed, float, stickers, name tag, StatTrak count and charms), with no account or network call. The older form holds only IDs that need a logged-in CS2 client to resolve, so the viewer says that rather than guessing.

The marketplace is the 2018 idea again: open a listing and the item loads in 3D at its own float and seed. The listings and prices are demo data.

The CS3D marketplace demo with a Galil AR Urban Rubble listing open in 3D, at Minimal Wear float 0.138706, seed 592, over a grid of demo listings with prices and floats

The creator studio exports a PNG, GIF, WebM or MP4 of an item from the render server. Pasting an inspect link replaces the controls, so the whole request is one URL.

The CS3D creator studio rendering an AWP Dragon Lore at float 0.04, seed 0, with PNG, GIF, WebM and MP4 export formats and the render server request URL

Getting it small enough to load

A procedural finish needs the weapon’s maps plus its pattern textures, and at full resolution that is a lot. A MAC-10 | Heat went from 141 MB to under 9 MB, measured on 10th August 2026:

  • not loading the weapon’s own maps where the finish covers them;
  • a 1,024 px texture set, since the viewer’s canvas is 512 to 1,400 px wide and the source maps are 4,096;
  • WebP textures and meshopt-compressed models;
  • fetching only the mesh that will be drawn.

One conversion went wrong in a way worth remembering. libwebp clears the colour under fully transparent pixels, which is exactly where the normal maps keep their data. The broken set measured 7.9 MB against the correct 9.5 MB and the encoder reported success both times, so the smaller file looked like a win. Only a render diff caught it. Every asset conversion now goes through a pixel diff, because file size cannot tell you a texture is right.

The pipeline processes a CS2 update in about 12 to 15 minutes, down from 4.2 hours, and its output is bit-for-bit reproducible, so a rebuild that changes nothing uploads nothing.

Version 1, 2018 to 2019

The original was a content script on CS:GO market listings (steamcommunity.com/market/listings/730/*) rendering the model with three.js. Getting the models out of the game was most of the work, and the repo’s HOW_TO.md documents the pipeline:

  1. Extract models and textures from the game files with GCFScape.
  2. Convert the textures with VTFEdit.
  3. Decompile the models with Crowbar.
  4. Import them into Blender with the Source tools and export to JSON for three.js.

Version 1 covered five knives, the Karambit, Flip, Bayonet, M9 Bayonet and Gut, each in Autotronic, Lore and Black Laminate. Fifteen fixed textures, against 1,388 finishes painted live now.

History

  • 4th February 2018: first commit.
  • 3rd March 2019: a refactor removed jQuery and split the renderer and config apart.
  • 9th March 2019: tagged v1.0.0, with the asset pipeline written up in HOW_TO.md.
  • 17th November 2024: started a CS2 rework on GitHub, split into an asset pipeline, a shared base, an iframe viewer and example integrations. It stopped at one work-in-progress commit.
  • 6th August 2026: started the current rewrite locally, deriving everything from CS2’s files.
  • 9th to 10th August 2026: the embed API and its delivery tiers, the containerised pipeline, and the compressed texture and model sets.

What is left

  • Nothing is public yet. v1.0.0 on GitHub is still the release, and the rewrite runs on my machine.
  • The compressed asset set (8.89 GB, against 33.10 GB for the full set) is still opt-in. It has to become the default, and be proved with a render diff, before anything is published.
  • The 312 painted finishes have no glitter, iridescence or overlay yet, and have not been checked against in-game screenshots the way the procedural ones have.

Weapon models and textures are Valve’s, extracted from the game files.