Insights Técnicos
Documentação educacional e histórica sobre como funciona o sistema que alimenta este site
Counter-Strike 2 e Counter Strike Global Offensive usam uma única textura base (como Case Hardened) para gerar centenas de variantes de skins com aparência única através de um sistema de transformações aleatórias. Isso é alcançado através de um mecanismo determinístico baseado em seed — uma chave para entender e reproduzir padrões Blue Gem fora do jogo.
Por que é chamado de "Seed" de Pintura?
Para gerar variedade de textura de forma consistente mas aleatória, a Valve emprega um gerador uniforme pseudo-aleatório incorporado ao Source Engine. Como os computadores são máquinas determinísticas, eles precisam de um valor inicial — uma seed — para produzir aleatoriedade. No CS2, cada skin recebe uma paint seed variando de 1 a 999. Esta seed inicializa o gerador de números aleatórios, que então produz um conjunto específico de valores usados para aplicar transformações à textura.
Como este algoritmo é determinístico e uniforme em todas as plataformas, uma determinada paint seed sempre produzirá a mesma transformação — garantindo que a skin pareça idêntica em todos os sistemas.
Resumo: A paint seed inicializa o gerador pseudo-aleatório da Valve para definir como a textura base é posicionada, rotacionada e escalada para as camadas de padrão, desgaste e sujeira.
Como as Transformações de Textura são Calculadas?
Para entender como o CS2 randomiza as aparências das skins, ajuda entender o mapeamento UV: cada modelo de arma tem um layout UV que define como uma textura 2D envolve a malha 3D. A Valve aplica a textura a este mapa UV e então usa a paint seed para randomizar sua translação, rotação e escala.
Isso afeta não apenas o padrão principal (como as manchas de cor do Case Hardened), mas também as sobreposições de desgaste e sujeira — texturas que adicionam arranhões, envelhecimento e sujeira.
Se o estilo de uma skin não usa deslocamento aleatório (por exemplo, possivelmente skins de cor sólida como Asiimov), ela não será afetada por este sistema.
Conceito de Mapeamento UV
Passe o mouse sobre as faces do cubo ou o mapa UV para ver como superfícies 3D mapeiam para coordenadas de textura 2D
3D Model
UV Map (Unfolded)
Passo a Passo: Paint Seed → Transformação
1. Determinar Escala Base
Cada arma e estilo de pintura tem uma escala específica, geralmente definida no items_game.txt da Valve. A escala base é calculada a partir do comprimento da arma e da escala UV, dependendo do estilo de pintura:
if (paint_style == 3 || paint_style == 6) {
scale = weapon_length * 0.027777778;
} else {
scale = uv_scale;
}Por exemplo, o Karambit tem:
- WeaponLength = 9.813000
- UVScale = 0.438000
- → resultando em uma escala base de 0.438
2. Gerar Valores Aleatórios
Uma vez que a escala base é conhecida, a paint seed é usada para gerar 11 valores float pseudo-aleatórios, que definem como cada camada de textura é aplicada:
| Camada de Textura | Parâmetros |
|---|---|
| Padrão | escala, translaçãoX, translaçãoY, rotação |
| Desgaste | escala × multiplicador, translaçãoX, translaçãoY, rotação |
| Sujeira | escala × multiplicador, translaçãoX, translaçãoY, rotação |
Esses floats são gerados em ordem e intervalos fixos:
Padrão
- translateX → 0.0 – 1.0
- translateY → 0.0 – 1.0
- rotate → 0.0 – 360.0
Desgaste
- scaleMult → 1.6 – 1.8
- translateX → 0.0 – 1.0
- translateY → 0.0 – 1.0
- rotate → 0.0 – 360.0
Sujeira
- scaleMult → 1.6 – 1.8
- translateX → 0.0 – 1.0
- translateY → 0.0 – 1.0
- rotate → 0.0 – 360.0
Esses valores são aplicados independentemente a cada camada usando a seguinte lógica:
Ordem de Transformação: Escala → Translação → Rotação(Repetido para padrão, desgaste e sujeira)Exemplo: Karambit | Case Hardened — Paint Seed 633
Usando a lógica acima, paint seed 633 em um Karambit produz:
- 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
As camadas de desgaste e sujeira obtêm seus próprios valores, também derivados da seed mas com diferentes multiplicadores e ângulos.
Mistério Restante: Centro de Rotação
Por muito tempo, uma questão permaneceu: onde exatamente está o pivô de rotação? Enquanto ângulos <180° pareciam girar em torno do canto superior esquerdo do UV, ângulos maiores se comportavam inconsistentemente ao tentar simular o resultado fora do jogo.
Do Reddit ao pattern.wiki
A primeira tentativa de engenharia reversa deste sistema veio do famoso post no Reddit de Step7750 em 2016. Esse post estabeleceu a ideia básica de como as transformações baseadas em seed funcionam — e por anos, serviu como a referência de facto para a comunidade.
Eventualmente, sites como Broskins e csfloat.com construíram sistemas de visualização funcionais — mas a lógica real usada pela Valve permaneceu não documentada para o público.
Isso mudou no início de 2024, quando pattern.wiki publicou uma análise completa do processo de transformação — incluindo valores específicos, matemática e exemplos visuais. Foi um grande avanço.
O Que Esclarecemos
Embora a implementação do pattern.wiki claramente funcione na prática, sua descrição da ordem de transformação e pivô de rotação não estava totalmente alinhada com o comportamento do Source por baixo dos panos. Através de testes e depuração, esclarecemos alguns pontos sutis (mas importantes):
- Todas as transformações são aplicadas em torno da origem (0, 0) — não após a translação
- A ordem efetiva da matriz é: T₂ × R × S × T₁
Aplicação de Transformação de Template (Modelo Finalizado)
Para amostrar a área correta da textura usando uma paint seed, aplicamos uma sequência de transformações afins — cada uma modificando as coordenadas UV antes de amostrar a textura base.
Cadeia de Transformação Passo a Passo
1. Translação Centralizada
Deslocar o padrão usando os deslocamentos da paint seed, mas centralizar a transformação em torno da origem UV:
translate(offsetX - 0.5, offsetY - 0.5)2. Escala (em torno da origem)
Escalar uniformemente o padrão usando a escala base — em torno da origem (0, 0):
scale(scaleX, scaleY)3. Rotação (em torno da origem)
Girar o padrão no sentido anti-horário a partir da origem:
rotate(rotation)4. Deslocamento Extra (ajuste final)
Após rotação e escala, aplicar um deslocamento final que compensa a rotação baseada em canto:
invScale = 0.5 / scaleangle = -rotationDeg * (π / 180)extraX = invScale * cos(angle) - invScale * sin(angle)extraY = (extraX * sin(angle)) + (invScale * cos(angle))translate(extraX, extraY)Sequência Final de Matriz
Em termos afins, isso cria uma matriz de transformação completa:
A = T₂ × R × S × T₁Ou em português simples:
- Centralizar deslocamento UV
- Aplicar escala
- Girar em torno da origem
- Corrigir com deslocamento extra
Os UVs transformados finais são então envolvidos usando módulo:
uv_final = (A × uv_coords) % 1.0Como o desgaste baseado no float é gerado
Valores de float mais altos fazem a skin parecer mais desgastada. Recriamos isso do mesmo jeito que o Counter-Strike faz — compondo três texturas sobre o padrão Case Hardened em luz linear, conforme o valor de float do item. Com float 0 (Nova de Fábrica) você vê o padrão limpo; com float 1 (Veterana de Guerra) o metal fica apagado, escurecido e granulado.
Padrão base
O padrão Case Hardened com gradiente de cores (azul / dourado / roxo), posicionado pela mesma transformação de seed descrita acima.
Mapa de desgaste
Um mapa em tons de cinza que decide quais partes da lâmina se desgastam primeiro — bordas salientes e áreas expostas antes das protegidas.
Mapa de sujeira (grunge)
Um mapa fino de sujeira e respingos que adiciona quebras realistas na superfície e imundície conforme o float aumenta.
O valor de float controla todo o efeito através de um único parâmetro. Arrastá-lo de 0 a 1 dessatura, escurece e suja progressivamente o padrão mantendo-o visível — a Case Hardened envelhece mudando de cor e acumulando sujeira, ela não se desgasta até o metal nu.
worn = compose(base, wear, grunge, AO, float) // float 0 = Factory New … 1 = Battle-Scarred
O mesmo motor de desgaste baseado em float, ao vivo — varrendo esta Karambit #387 de Nova de Fábrica a Veterana de Guerra.
O granulado ('Maserung') vem da geometria da arma
Toda arma tem um mapa de cavidade / oclusão de ambiente (AO) pré-renderizado. O desgaste e a sujeira se concentram nas fendas e ao longo das bordas, o que produz aquele granulado mosqueado característico que você vê numa lâmina veterana de guerra. Cada faca usa seu próprio mapa de AO, então o padrão de desgaste é único para o formato daquela arma.
- Posicione o padrão Case Hardened, o mapa de desgaste e o mapa de grunge usando as transformações de seed de cada padrão.
- Use o valor de float para decidir o quão intensamente cada pixel se desgasta, ponderado pelo mapa de cavidade / AO da arma.
- Dessature e escureça as áreas desgastadas em direção a um tom de sujeira, e adicione sujeira fina a partir do mapa de grunge.
- Componha tudo em luz linear e exiba ao vivo no modelo 3D enquanto você arrasta o controle deslizante.
Esta é a matemática exata do próprio shader de acabamento do Counter-Strike, recuperada e reproduzida — então o visual desgastado que você visualiza corresponde a como o item realmente aparece no jogo.
Para entender melhor esta abordagem, você pode experimentar nosso estúdio de transformação de textura que aplica exatamente essas transformações ao vivo em seu próprio navegador.