# Gerenciamento de cor

## O que é um espaço de cor?

Cada espaço de cor é uma coleção de várias decisões de design, escolhidas em conjunto para dar suporte a uma grande variedade de cores, satisfazendo as restrições técnicas relacionadas à precisão e a tecnologia das telas. Ao criar um recurso 3D ou ao montar recursos 3D em uma cena, é importante saber quais são essas propriedades e como as propriedades de um espaço de cores se relacionam com outros espaços de cor na cena.

Cores sRGB e ponto branco (D65) exibidos no diagrama de referência cromaticidade CIE 1931. A região colorida representa uma projeção 2D da gama sRGB, que é um volume 3D. Fonte: Wikipedia

- Cores primárias: As cores primárias (por exemplo, vermelho, verde, azul) não são absolutas; elas são selecionadas a partir do espectro visível com base em restrições de precisão limitada e capacidades dos dispositivos de exibição disponíveis. As cores são expressas como uma proporção das cores primárias.
- Ponto branco: a maioria dos espaços de cores é projetada de forma que uma soma igualmente ponderada das primárias R = G = B parecerão sem cor, ou "acromáticas". A aparência de valores acromáticos (como branco ou cinza) dependem da percepção humana, que por sua vez depende fortemente no contexto do observador. Um espaço de cor especifica seu "ponto branco" para equilibrar essas necessidades. O ponto branco definido pelo espaço de cores sRGB é [link:https://en.wikipedia.org/wiki/Illuminant_D65 D65].
- Transfer functions: depois de escolher a gama de cores e um modelo de cores, ainda precisamos definir mapeamentos ("transfer functions") de valores numéricos para o espaço de cores. r = 0,5 representa 50% menos iluminação física do que r = 1.0? Ou 50% menos brilhante, conforme percebido por um olho humano médio? São coisas diferentes, e essa diferença pode ser representada como uma função matemática. As transfer functions podem ser lineares ou não lineares, dependendo dos objetivos do espaço de cores. sRGB define transfer functions não lineares. Aquelas funções são às vezes aproximadas como funções gamma, mas o termo "gamma" é ambíguo e deve ser evitado neste contexto.

Esses três parâmetros — cores primárias, ponto branco e transfer functions — definem um espaço de cores, cada um escolhido para objetivos particulares. Tendo definido os parâmetros, alguns termos adicionais são úteis:

- Modelo de cores: Sintaxe para identificar numericamente as cores dentro da gama de cores escolhida — um sistema de coordenadas para cores. No three.js estamos preocupados principalmente com o modelo de cor RGB, tendo três coordenadas r, g, b ∈ [0,1] ("domínio fechado") ou r, g, b ∈ [0,∞] ("domínio aberto"), cada um representando uma fração de uma cor primária. Outros modelos de cores (HSL, Lab, LCH) são comumente usados ​​para controle artístico.
- Gama de cores: uma vez que as cores primárias e um ponto branco tenham sido escolhidos, eles representam um volume dentro do espectro visível (uma "gama"). Cores fora deste volume ("fora da gama") não podem ser expressas por valores RGB de domínio fechado [0,1]. No domínio aberto [0,∞], a gama é tecnicamente infinita.

Considere dois espaços de cores muito comuns: [page:SRGBColorSpace] ("sRGB") e [page:LinearSRGBColorSpace] ("Linear-sRGB"). Ambos usam as mesmas cores primárias e ponto branco, e, portanto, têm a mesma gama de cores. Ambos usam o modelo de cores RGB. Eles diferem apenas nas transfer functions — Linear-sRGB é linear em relação à intensidade da luz física. sRGB usa as transfer functions sRGB não lineares e se assemelha mais à maneira que o olho humano percebe a luz e a capacidade de resposta de dispositivos de exibição comuns.

Essa diferença é importante. Cálculos de iluminação e outras operações de renderização devem geralmente ocorrem em um espaço de cores linear. No entanto, cores lineares são menos eficientes para armazenar em uma imagem ou framebuffer e não parecem corretas quando vistas por um observador humano. Como resultado, as texturas de entrada e a imagem final renderizada geralmente usarão o método não linear do espaço de cores sRGB.

> ℹ️ AVISO: Embora alguns monitores modernos sejam compatíveis com gamas mais amplas, como Display-P3, as APIs gráficas da plataforma web dependem em grande parte do sRGB. Aplicativos que usam three.js hoje normalmente usarão apenas os espaços de cores sRGB e Linear-sRGB.

## Atribuições dos espaços de cores

Fluxos de trabalho lineares - necessários para métodos modernos de renderização - geralmente envolvem mais de um espaço de cores, cada um atribuído a uma função específica. Espaços de cores lineares e não lineares são apropriados para diferentes funções, como explicado abaixo.

### Input do espaço de cores

Cores fornecidas ao three.js — de seletores de cores, texturas, modelos 3D e outras fontes — cada um tem um espaço de cor associado. Aqueles que ainda não estão na cor de trabalho Linear-sRGB, devem ser convertidos e as texturas devem receber a atribuição texture.colorSpace correta. Certas conversões (para cores hexadecimais e CSS em sRGB) podem ser feitas automaticamente se o modo de gerenciamento de cores herdado é desabilitado antes de inicializar as cores:

`THREE.ColorManagement.enabled = true;`

- Materiais, luzes e shaders: cores nos materiais, luzes e shaders armazenam componentes RGB no espaço de cores de trabalho Linear-sRGB.
- Cores de vértices: [page:BufferAttribute BufferAttributes] armazena componentes RGB no Espaço de cores de trabalho linear-sRGB.
- Texturas de cores: PNG ou JPEG [page:Texture Textures] contendo informações de cores (como .map ou .emissiveMap) usam o espaço de cores sRGB de domínio fechado e devem ser anotados com texture.colorSpace = SRGBColorSpace. Formatos como OpenEXR (às vezes usado para .envMap ou .lightMap) usam o espaço de cores Linear-sRGB indicado com texture.colorSpace = LinearSRGBColorSpace, e podem conter valores no domínio aberto [0,∞].
- Texturas não coloridas: Texturas que não armazenam informações de cores (como .normalMap ou .roughnessMap) não têm um espaço de cores associado e geralmente usam a textura (padrão) como texture.colorSpace = NoColorSpace. Em casos raros, dados sem cor podem ser representados com outras codificações não lineares por motivos técnicos.

> ⚠️ AVISO: Muitos formatos para modelos 3D não funcionam de forma correta ou consistente na definição das informações do espaço de cores. Enquanto o three.js tenta lidar com a maioria dos casos, problemas são comuns com formatos de arquivo mais antigos. Para melhores resultados, use glTF 2.0 ([page:GLTFLoader]) e teste modelos 3D em visualizadores on-line antecipadamente para confirmar que o recurso em si está correto.

### Espaço de cores de trabalho

Renderização, interpolação e muitas outras operações devem ser executadas em um domínio aberto do espaço de cores de trabalho linear, no qual os componentes RGB são proporcionais a iluminação física. No three.js, o espaço de cores de trabalho é Linear-sRGB.

### Output do espaço de cores

A saída para um dispositivo de exibição, imagem ou vídeo pode envolver a conversão do domínio aberto do espaço de cores de trabalho linear-sRGB para outro espaço de cores. Essa conversão pode ser feita em uma passagem de renderização principal ([page:WebGLRenderer.outputColorSpace]), ou durante o pós-processamento.

`renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing`

- Tela: as cores gravadas em um canvas WebGL para exibição devem estar no espaço sRGB colorido.
- Imagem: as cores gravadas em uma imagem devem usar o espaço de cores apropriado para o formato e o uso. Imagens totalmente renderizadas gravadas em texturas PNG ou JPEG geralmente usam o espaço de cores sRGB. Imagens contendo emissão, mapas de luz ou outros dados não confinados ao intervalo [0,1] geralmente usarão o espaço de cores Linear-sRGB de domínio aberto, e um formato de imagem compatível como OpenEXR.

> ⚠️ AVISO: Os render targets podem usar sRGB ou Linear-sRGB. sRGB faz melhor uso de precisão limitada. No domínio fechado, 8 bits geralmente são suficientes para sRGB enquanto que ≥12 bits (meio flutuante) podem ser necessários para Linear-sRGB. Se mais tarde os estágios pipeline precisarem de entrada Linear-sRGB, as conversões adicionais podem ter um pequeno custo de desempenho.

Custom materials based on [page:ShaderMaterial] and [page:RawShaderMaterial] have to implement their own output color space conversion. For instances of `ShaderMaterial`, adding the `colorspace_fragment` shader chunk to the fragment shader's `main()` function should be sufficient.

## Trabalhando com instâncias THREE.Color

Métodos de leitura ou modificação de instâncias [page:Color] assumem que os dados já estão no espaço de cores de trabalho three.js, Linear-sRGB. Os componentes RGB e HSL são representações diretas de dados armazenados pela instância Color e nunca são convertidos implicitamente. Os dados de cores podem ser convertidos explicitamente com .convertLinearToSRGB() ou .convertSRGBToLinear().

`// RGB components (no change). color.r = color.g = color.b = 0.5; console.log( color.r ); // → 0.5 // Manual conversion. color.r = 0.5; color.convertSRGBToLinear(); console.log( color.r ); // → 0.214041140`

Com ColorManagement.enabled = true definido (recomendado), determinadas conversões são feitas automaticamente. Como as cores hexadecimais e CSS geralmente são sRGB, métodos [page:Color] irão converter automaticamente essas entradas de sRGB para Linear-sRGB em setters, ou converter de Linear-sRGB para sRGB ao retornar hexadecimal ou CSS de getters.

`// Hexadecimal conversion. color.setHex( 0x808080 ); console.log( color.r ); // → 0.214041140 console.log( color.getHex() ); // → 0x808080 // CSS conversion. color.setStyle( 'rgb( 0.5, 0.5, 0.5 )' ); console.log( color.r ); // → 0.214041140 // Override conversion with 'colorSpace' argument. color.setHex( 0x808080, LinearSRGBColorSpace ); console.log( color.r ); // → 0.5 console.log( color.getHex( LinearSRGBColorSpace ) ); // → 0x808080 console.log( color.getHex( SRGBColorSpace ) ); // → 0xBCBCBC`

## Erros comuns

Quando uma cor ou textura individual é configurada incorretamente, ela aparecerá mais escura ou mais clara do que esperado. Quando o espaço de cores de saída do renderizador está mal configurado, a cena inteira pode aparecer mais escura (por exemplo, conversão ausente para sRGB) ou mais clara (por exemplo, uma conversão dupla para sRGB com pós-processamento). Em cada caso, o problema pode não ser uniforme e simplesmente aumentar/diminuir a iluminação não resolve.

Um problema mais sutil aparece quando ambos os espaços de cores de entrada e saída estão incorretos — os níveis gerais de brilho podem ser bons, mas as cores podem mudar inesperadamente sob iluminação diferente, ou o sombreamento pode parecer mais estourado e menos suave do que o pretendido. Esses dois erros não fazem um acerto, e é importante que o trabalho espaço de cores funcional seja linear ("cena referida") e o espaço de cores de saída seja não linear ("exibição referida").

## Leitura adicional

- GPU Gems 3: The Importance of Being Linear, de Larry Gritz and Eugene d'Eon
- What every coder should know about gamma, de John Novak
- The Hitchhiker's Guide to Digital Color, de Troy Sobotka
- Color Management, Blender