Détails Techniques
Documentation éducative et historique sur le fonctionnement du système qui alimente ce site
Transformations de Motifs
Counter-Strike 2 et Counter Strike Global Offensive utilisent une seule texture de base (comme Case Hardened) pour générer des centaines de variantes de skins d'apparence unique grâce à un système de transformations aléatoires. Ceci est réalisé via un mécanisme déterministe basé sur une graine — une clé pour comprendre et reproduire les motifs Blue Gem en dehors du jeu.
Pourquoi l'appelle-t-on Paint "Seed" ?
Pour générer une variété de textures de manière cohérente mais aléatoire, Valve utilise un générateur uniforme pseudo-aléatoire intégré au moteur Source. Comme les ordinateurs sont des machines déterministes, ils nécessitent une valeur initiale — une graine — pour produire du hasard. Dans CS2, chaque skin se voit attribuer un paint seed allant de 1 à 999. Cette graine initialise le générateur de nombres aléatoires, qui produit ensuite un ensemble spécifique de valeurs utilisées pour appliquer des transformations à la texture.
Parce que cet algorithme est déterministe et uniforme sur toutes les plateformes, un paint seed donné produira toujours la même transformation — garantissant que le skin a l'air identique sur chaque système.
TL;DR : Le paint seed initialise le générateur pseudo-aléatoire de Valve pour définir comment la texture de base est positionnée, tournée et mise à l'échelle pour les couches de motif, d'usure et de saleté.
Comment sont calculées les transformations de textures ?
Pour comprendre comment CS2 randomise l'apparence des skins, il est utile de comprendre le mapping UV : chaque modèle d'arme a une disposition UV qui définit comment une texture 2D s'enroule autour du maillage 3D. Valve applique la texture à cette carte UV, puis utilise le paint seed pour randomiser sa translation, rotation et échelle.
Cela affecte non seulement le motif principal (comme les taches de couleur Case Hardened), mais aussi les superpositions d'usure et de saleté — des textures qui ajoutent des rayures, du vieillissement et de la crasse.
Si le style d'un skin n'utilise pas de déplacement aléatoire (par exemple, possiblement des skins de couleur unie comme Asiimov), il ne sera pas affecté par ce système.
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)
Étape par étape : Paint Seed → Transformation
1. Déterminer l'échelle de base
Chaque arme et style de peinture a une échelle spécifique, généralement définie dans le fichier items_game.txt de Valve. L'échelle de base est calculée à partir de la longueur de l'arme et de l'échelle UV, selon le style de peinture :
if (paint_style == 3 || paint_style == 6) {
scale = weapon_length * 0.027777778;
} else {
scale = uv_scale;
}Par exemple, le Karambit a :
- WeaponLength = 9.813000
- UVScale = 0.438000
- → résultant en une échelle de base de 0.438
2. Générer des valeurs aléatoires
Une fois l'échelle de base connue, le paint seed est utilisé pour générer 11 valeurs float pseudo-aléatoires, qui définissent comment chaque couche de texture est appliquée :
| Couche de texture | Paramètres |
|---|---|
| Motif | échelle, translationX, translationY, rotation |
| Usure | échelle × multiplicateur, translationX, translationY, rotation |
| Saleté | échelle × multiplicateur, translationX, translationY, rotation |
Ces floats sont générés dans un ordre et des plages fixes :
Motif
- translateX → 0.0 – 1.0
- translateY → 0.0 – 1.0
- rotate → 0.0 – 360.0
Usure
- scaleMult → 1.6 – 1.8
- translateX → 0.0 – 1.0
- translateY → 0.0 – 1.0
- rotate → 0.0 – 360.0
Saleté
- 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)Exemple : Karambit | Case Hardened — Paint Seed 633
En utilisant la logique ci-dessus, le paint seed 633 sur un Karambit donne :
- 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
Les couches d'usure et de saleté obtiennent leurs propres valeurs, également dérivées de la graine mais avec des multiplicateurs et angles différents.
Remaining Mystery: Rotation Center
Pendant longtemps, une question est restée : où exactement se trouve le pivot de rotation ? Alors que les angles <180° semblaient tourner autour du coin supérieur gauche de l'UV, les angles plus élevés se comportaient de manière incohérente lors des tentatives de simulation du résultat en dehors du jeu.
From Reddit to pattern.wiki
La première tentative de rétro-ingénierie de ce système est venue du célèbre post Reddit de Step7750 en 2016. Ce post a exposé l'idée de base du fonctionnement des transformations basées sur la graine — et pendant des années, il a servi de référence de facto pour la communauté.
Finalement, des sites comme Broskins et csfloat.com ont construit des systèmes de prévisualisation fonctionnels — mais la logique réelle utilisée par Valve restait non documentée pour le public.
Cela a changé début 2024, quand pattern.wiki a publié une analyse complète du processus de transformation — incluant des valeurs spécifiques, des mathématiques et des exemples visuels. C'était un bond en avant majeur.
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. Translation centrée
Décaler le motif en utilisant les décalages du paint seed, mais centrer la transformation autour de l'origine UV :
translate(offsetX - 0.5, offsetY - 0.5)2. Échelle (autour de l'origine)
Mettre à l'échelle uniformément le motif en utilisant l'échelle de base — autour de l'origine (0, 0) :
scale(scaleX, scaleY)3. Rotation (autour de l'origine)
Faire tourner le motif dans le sens antihoraire depuis l'origine :
rotate(rotation)4. Décalage supplémentaire (ajustement final)
Après rotation et échelle, appliquer un décalage final qui compense la rotation basée sur le coin :
invScale = 0.5 / scaleangle = -rotationDeg * (π / 180)extraX = invScale * cos(angle) - invScale * sin(angle)extraY = (extraX * sin(angle)) + (invScale * cos(angle))translate(extraX, extraY)Séquence de matrice finale
En termes affines, cela crée une matrice de transformation complète :
A = T₂ × R × S × T₁Ou en langage simple :
- Centrer le décalage UV
- Appliquer l'échelle
- Tourner autour de l'origine
- Corriger avec un décalage supplémentaire
Les UV finaux transformés sont ensuite enveloppés en utilisant modulo :
uv_final = (A × uv_coords) % 1.0Pour mieux comprendre cette approche, vous pouvez jouer avec notre studio de transformation de textures qui applique exactement ces transformations en direct dans votre propre navigateur.
