Tekniska Detaljer
Utbildnings- och historisk dokumentation om hur systemet som driver denna webbplats fungerar
Mönstertransformationer
Counter-Strike 2 och Counter Strike Global Offensive anvĂ€nder en enda bastextur (som Case Hardened) för att generera hundratals unikt utseende skin-varianter genom ett system av randomiserade transformationer. Detta uppnĂ„s via en deterministisk, frö-baserad mekanism â en nyckel till att förstĂ„ och reproducera Blue Gem-mönster utanför spelet.
Varför kallas det ett Paint "Seed"?
För att generera texturvariation pĂ„ ett konsekvent men randomiserat sĂ€tt anvĂ€nder Valve en pseudo-slumpmĂ€ssig enhetlig generator inbyggd i Source Engine. Eftersom datorer Ă€r deterministiska maskiner krĂ€ver de ett initialt vĂ€rde â ett frö â för att producera slumpmĂ€ssighet. I CS2 tilldelas varje skin ett paint seed frĂ„n 1 till 999. Detta frö initialiserar slumptalsgeneratorn, som sedan producerar en specifik uppsĂ€ttning vĂ€rden som anvĂ€nds för att tillĂ€mpa transformationer pĂ„ texturen.
Eftersom denna algoritm Ă€r deterministisk och enhetlig över alla plattformar kommer ett givet paint seed alltid att ge samma transformation â vilket sĂ€kerstĂ€ller att skinnet ser identiskt ut pĂ„ varje system.
TL;DR: Paint seed initialiserar Valves pseudo-slumpmÀssiga generator för att definiera hur bastexturen positioneras, roteras och skalas för mönster-, slitage- och smutslagren.
Hur berÀknas texturtransformationer?
För att förstÄ hur CS2 randomiserar skin-utseenden hjÀlper det att förstÄ UV-mappning: varje vapenmodell har en UV-layout som definierar hur en 2D-textur wrappas runt 3D-meshen. Valve tillÀmpar texturen pÄ denna UV-karta och anvÀnder sedan paint seed för att randomisera dess translation, rotation och skala.
Detta pĂ„verkar inte bara huvudmönstret (som Case Hardened fĂ€rgflĂ€ckar), utan ocksĂ„ slitage- och smutsöverlĂ€ggen â texturer som lĂ€gger till repor, Ă„ldrande och smuts.
Om en skins stil inte anvÀnder slumpmÀssig förskjutning (t.ex. möjligen enfÀrgade skins som Asiimov), kommer den inte att pÄverkas av detta system.
UV Mapping Concept
Hover over the cube faces or UV map to see how 3D surfaces map to 2D texture coordinates
3D Model
UV Map (Unfolded)
Steg-för-steg: Paint Seed â Transformation
1. BestÀm basskala
Varje vapen och mÄlningsstil har en specifik skala, vanligtvis definierad i Valves items_game.txt. Basskalan berÀknas frÄn vapenlÀngden och UV-skalan, beroende pÄ mÄlningsstilen:
if (paint_style == 3 || paint_style == 6) {
    scale = weapon_length * 0.027777778;
} else {
    scale = uv_scale;
}Till exempel har Karambit:
- WeaponLength = 9.813000
- UVScale = 0.438000
- â vilket resulterar i en basskala pĂ„ 0.438
2. Generera slumpmÀssiga vÀrden
NÀr basskalan Àr kÀnd anvÀnds paint seed för att generera 11 pseudo-slumpmÀssiga float-vÀrden, som definierar hur varje texturlager tillÀmpas:
| Texturlager | Parametrar |
|---|---|
| Mönster | skala, translateX, translateY, rotation |
| Slitage | skala Ă multiplikator, translateX, translateY, rotation |
| Smuts | skala Ă multiplikator, translateX, translateY, rotation |
Dessa floats genereras i fast ordning och intervall:
Mönster
- translateX â 0.0 â 1.0
- translateY â 0.0 â 1.0
- rotate â 0.0 â 360.0
Slitage
- scaleMult â 1.6 â 1.8
- translateX â 0.0 â 1.0
- translateY â 0.0 â 1.0
- rotate â 0.0 â 360.0
Smuts
- scaleMult â 1.6 â 1.8
- translateX â 0.0 â 1.0
- translateY â 0.0 â 1.0
- rotate â 0.0 â 360.0
These values are applied independently to each layer using the following logic:
Transform Order: Scale â Translate â Rotate(Repeated for pattern, wear, and grunge)Exempel: Karambit | Case Hardened â Paint Seed 633
Med ovanstÄende logik ger paint seed 633 pÄ en Karambit:
- Base Scale: 0.438
- Translate X: 0.471 â shifts the pattern ~47% left
- Translate Y: 0.624 â shifts the pattern ~62% up
- Rotation: 96.7° counterclockwise
Slitage- och smutslagren fÄr sina egna vÀrden, ocksÄ hÀrledda frÄn fröet men med olika multiplikatorer och vinklar.
Remaining Mystery: Rotation Center
Under lÄng tid kvarstod en frÄga: var exakt Àr rotationspunkten? Medan <180° vinklar verkade rotera runt UV:ns övre vÀnstra hörn, betedde sig högre vinklar inkonsekvent nÀr man försökte simulera resultatet utanför spelet.
From Reddit to pattern.wiki
Det tidigaste försöket att bakĂ„tkonstruera detta system kom frĂ„n det berömda Reddit-inlĂ€gget av Step7750 tillbaka 2016. Det inlĂ€gget lade ut grundidĂ©n om hur frö-baserade transformationer fungerar â och i Ă„ratal fungerade det som de facto-referens för communityn.
Till slut byggde sajter som Broskins och csfloat.com fungerande förhandsgranskningssystem â men den faktiska logiken som Valve anvĂ€nde förblev odokumenterad för allmĂ€nheten.
Det Ă€ndrades i början av 2024, nĂ€r pattern.wiki publicerade en fullstĂ€ndig nedbrytning av transformationsprocessen â inklusive specifika vĂ€rden, matematik och visuella exempel. Det var ett stort steg framĂ„t.
What We Clarified
While pattern.wiki's implementation clearly works in practice, their description of the transform order and rotation pivot didn't fully align with how Source behaves under the hood. Through testing and debugging, we clarified a few subtle (but important) points:
- All transforms are applied around the origin (0, 0) â not after translation
- The effective matrix order is: Tâ Ă R Ă S Ă Tâ
Template Transform Application (Finalized Model)
To sample the correct area of the texture using a paint seed, we apply a sequence of affine transformations â each one modifying the UV coordinates before sampling the base texture.
Step-by-Step Transform Chain
1. Centrerad translation
Förskjut mönstret med paint seedets offsets, men centrera transformationen runt UV-origo:
translate(offsetX - 0.5, offsetY - 0.5)2. Skala (runt origo)
Enhetligt skala mönstret med basskalan â runt origo (0, 0):
scale(scaleX, scaleY)3. Rotation (runt origo)
Rotera mönstret moturs frÄn origo:
rotate(rotation)4. Extra offset (slutlig justering)
Efter rotation och skala, tillÀmpa en slutlig offset som kompenserar för den hörnbaserade rotationen:
invScale = 0.5 / scaleangle = -rotationDeg * (Ï / 180)extraX = invScale * cos(angle) - invScale * sin(angle)extraY = (extraX * sin(angle)) + (invScale * cos(angle))translate(extraX, extraY)Slutlig matrissekvens
I affina termer skapar detta en fullstÀndig transformationsmatris:
A = Tâ Ă R Ă S Ă TâEller pĂ„ ren svenska:
- Centrera UV-offset
- TillÀmpa skala
- Rotera runt origo
- Korrigera med extra offset
De slutliga transformerade UV:erna wrappas sedan med modulo:
uv_final = (A à uv_coords) % 1.0För att bÀttre förstÄ detta tillvÀgagÄngssÀtt kan du leka med vÄr texturtransformationsstudio som tillÀmpar exakt dessa transformationer live i din egen webblÀsare.
