# Gestione del colore ([name])

## Cos'è lo spazio colore?

Ogni spazio colore è una collezione di diverse decisioni progettuali, scelte insieme per supportare un'ampia gamma di colori e al contempo soddisfare i vincoli tecnici legati alla precisione e alle tecnologie di visualizzazione. Quando si crea una risorsa 3D, o si assemblano delle risorse 3D insieme in una scena, è importante sapere quali sono queste proprietà e come le proprietà di uno spazio colore si relazionano con altri spazi colore nella scena.

Colori sRGB e il punto di bianco (D65) visualizzati nel diagramma cromatico di riferimento CIE 1931. La regione colorata rappresenta una proiezione 2D della gamma sRGB, che è un volume 3D. Fonte: Wikipedia

- Colori primari: I colori primari (rosso, verde, blu) non sono assoluti; vengono selezionati dallo spettro visibile in base ai vincoli di precisione limitata e alla capacità dei dispositivi di visualizzazione disponibili. I colori sono espressi come rapporto tra i colori primari.
- Punto di bianco: La maggior parte degli spazi colore è progettata in modo tale che una somma equamente ponderata di primari R = G = B appaia priva di colore o "acromatica". L'aspetto dei valori cromatici (come il bianco o il grigio) dipende dalla percezione umana, che a sua volta dipende fortemente dal contesto dell'osservatore. Uno spazio colore specifica il suo "punto di bianco" per bilanciare queste esigenze. Il punto di bianco definito dallo spazio colore sRGB è D65.
- Funzioni di trasferimento (transfer functions): Dopo aver scelto la gamma cromatica e un modello di colore, dobbiamo ancora definire le mappature ("funzioni di trasferimento") dei valori numerici da/verso lo spazio colore. R = 0,5 rappresenta il 50% in meno di illuminazione fisica rispetto a r = 1,0? O il 50% in meno di luminosità, come percepito da un occhio umano medio? Sono cose diverse e questa differenza può essere rappresentata come una funzione matematica. Le funzioni di trasferimento possono essere lineari o non lineari, a seconda degli obiettivi dello spazio colore. sRGB definisce funzioni di trasferimento non lineari. Queste funzioni sono talvolta approssimate come funzioni gamma, ma il termine "gamma" è ambiguo e dovrebbe essere evitato in questo contesto.

Questi tre parametri - colori primari, punto di bianco e funzioni di trasferimento - definiscono uno spazio colore, ognuno scelto per obiettivi specifici. Dopo aver definito i parametri, sono utili alcuni termini aggiuntivi:

- Modello di colore: Sintassi per identificare numericamente i colori all'interno della gamma cromatica scelta - un sistema di coordinate per i colori. In three.js ci occupiamo principalmente del modello di colore RGB, con tre coordinate r, g, b ∈ [0,1] ("dominio chiuso") o r, g, b ∈ [0,∞] ("dominio aperto") che rappresentano ciascuna una frazione di un colore primario. Altri modelli di colore (HSL, Lab, LCH) sono comunemente utilizzati per il controllo artistico.
- Gamma di colori: Quando i colori primari e il punto di bianco sono stati scelti, questi rappresentano un volume all'interno dello spettro visibile (un "gamut"). I colori che non rientrano in questo volume ("fuori gamut") non possono essere espressi dai valori RGB del dominio chiuso [0,1]. Nel dominio aperto [0,∞], il gamut è tecnicamente infinito.

Consideriamo due spazi colori comuni: [page:SRGBColorSpace] ("sRGB") e [page:LinearSRGBColorSpace] ("Linear-sRGB"). Entrambi usano gli stessi colori primari e lo stesso punto di bianco, e quindi hanno la stessa gamma di colori. Entrambi utilizzano il modello di colore RGB. Sono diversi solo nelle funzioni di trasferimento - Linear-sRGB è lineare rispetto all'intensità della luce fisica, mentre sRGB utilizza le funzioni di trasferimento non lineari di sRGB e si avvicina maggiormente al modo in cui l'occhio umano percepisce la luce e alla reattività dei comuni dispositivi di visualizzazione.

Questa differenza è importante. I calcoli di illuminazione e altre operazioni di rendering devono generalmente avvenire in uno spazio di colore lineare. Tuttavia, i colori lineari sono meno efficienti da memorizzare in un'immagine o in un framebuffer e non hanno un aspetto corretto quando vengono osservati da un osservatore umano. Di conseguenza, le texture di input e l'immagine finale renderizzata utilizzano generalmente lo spazio di colore sRGB non lineare.

> ℹ️ ATTENZIONE: Anche se alcuni display moderni supportano gamme più ampie come Display-P3, le API grafiche della piattaforma web si basano in gran parte su sRGB. Le applicazioni che utilizzano three.js oggi utilizzano in genere solo gli spazi colore sRGB e Linear-sRGB.

## Ruoli degli spazi colore

Un flusso di lavoro lineare - richiesto per moderni metodi di rendering - generalmente coinvolge più di uno spazio di colore, ognuno assegnato ad un ruolo specifico. Spazi colore lineari o non lineari sono adatti a ruoli diversi, come spiegato di seguito.

### Input color space

I colori forniti a three.js - dai color picker, dalle texture, dai modelli 3D e da altre risorse - hanno ciascuno uno spazio colore associato. Quelli che non sono già nello spazio colore di lavoro Linear-sRGB devono essere convertiti e alle texture deve essere assegnata la corretta assegnazione texture.colorSpace. Alcune conversioni (per i colori esadecimali e CSS in sRGB) possono essere effettuate automaticamente se la modalità di gestione del colore legacy è disabilitata prima dell'inizializzazione dei colori:

`THREE.ColorManagement.enabled = true;`

- Materiali, luci, e shader: I colori nei materiali, nelle luci e negli shader memorizzano i componenti RGB nello spazio colore di lavoro Linear-sRGB.
- Colori dei vertici: [page:BufferAttribute BufferAttributes] memorizza i componenti RGB nello spazio colore di lavoro Linear-sRGB.
- Colori delle texture: Le [page:Texture Texture] PNG o JPEG contenti informazioni sul colore (come .map o .emissiveMap) usano lo spazio colore sRGB a dominio chiuso, e devono essere annotate con texture.colorSpace = SRGBColorSpace. I formati come OpenEXR (a volte usati per .envMap o .lightMap) utilizzano lo spazio colore Linear-sRGB indicato con texture.colorSpace = LinearSRGBColorSpace, e possono contenere valori nel dominio aperto [0,∞].
- Texture non a colori: Le texture che non memorizzano informazioni relative ai colori (come .normalMap o .roughnessMap) non hanno associato uno spazio colore, e generalmente usano l'annotazione (predefinita) texture.colorSpace = NoColorSpace. In rari casi, i dati non a colori possono essere rappresentati con altre codifiche non lineari per motivi tecnici.

> ⚠️ ATTENZIONE: Molti formati per modelli 3D non definiscono correttamente o in modo coerente le informazioni sullo spazio colore. Sebbene three.js tenti di gestire la maggior parte dei casi, i problemi sono spesso con i file con formati meno recenti. Per ottenere un miglior risultato bisogna utilizzare il formato glTF 2.0 ([page:GLTFLoader]) e prima bisogna testare i modelli 3D in visualizzatori online per confermare che la risorsa stessa sia corretta.

### Spazio colore di lavoro

Rendering, interpolazione e molte altre operazioni devono essere eseguite in uno spazio colore di lavoro lineare, nel quale i componenti RGB sono proporzionali all'illuminazione fisica. In three.js, lo spazio colore di lavoro è Linear-sRGB.

### Output color space

L'output su un dispositivo di visualizzazione, a un'immagine o a un video, può comportare la conversione dallo spazio colore di lavoro Linear-sRGB di dominio aperto a un altro spazio di colore. Questa conversione può essere eseguita nel passaggio di rendering principale ([page:WebGLRenderer.outputColorSpace]), o durante il post-processing.

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

- Display: I colori scritti in un canvas WebGL per i display devono essere nello spazio colore sRGB.
- Immagine: I colori scritti su un'immagine devono utilizzare lo spazio colore appropriato per il formato e per il suo uso. Le immagini completamente renderizzate scritte per texture PNG o JPEG generalmente usano lo spazio colore sRGB. Immagini contenenti emissioni, mappe di luce, o altri dati non limitati all'intervallo [0,1] utilizzaranno generalmente lo spazio colore Linear-sRGB a dominio aperto, e un formato immagine compatibile come OpenEXR.

> ⚠️ ATTENZIONE: I target di rendering possono utilizzare sia sRGB che Linear-sRGB. sRGB utilizza meglio la precisione limitata. Nel dominio chiuso, 8 bit sono sufficienti per sRGB mentre ≥12 (mezzo float) possono essere richiesti per Linear-sRGB. Se gli stadi successivi delle pipeline richiedono un ingresso Linear-sRGB, le conversioni aggiuntive possono avere un piccolo costo in termini di prestazioni.

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.

## Lavorare con le istanze di THREE.Color

I metodi di lettura o modifica delle istanze [page:Color] presuppongono che i dati siano già nello spazio colore di lavoro di three.js, Linear-sRGB. I componenti RGB e HSL sono rappresentazioni dirette dei dati memorizzati dall'istanza Color, e non sono mai convertiti implicitamente. I dati di Color possono essere esplicitamenre convertiti con .convertLinearToSRGB() o .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`

Con ColorManagement.enabled = true impostato (consigliato), alcune conversioni vengono effettuate automaticamente. Poiché i colori esadecimali e CSS sono generalmente sRGB, i metodi [page:Color] convertiranno automaticamente questi input da sRGB a Linear-sRGB nei setter, oppure convertiranno da Linear-sRGB a sRGB quando restituiscono output esadecimali o CSS dai getter.

`// 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`

## Errori comuni

Quando un singolo colore o una texture non sono configurati correttamente, apparirà più scuro o più chiaro del previsto. Quando lo spazio colore di output del renderer non è configurato correttamente, l'intera scena potrebbe essere più scura (ad es. manca la conversione ad sRGB) o più chiara (ad es. una doppia conversione a sRGB con post-processing). In ogni caso il problema potrebbe non essere uniforme e semplicemente aumentare/dimunire la luminosità non lo risolverebbe.

Un problema più sottile si verifica quando entrambi lo spazio colore di input e quello di output non sono corretti - i livelli di luminosità complessivi potrebbero andare bene, ma i colori potrebbero cambiare in modo imprevisto in condizioni di illuminazione diversa o l'ombreggiatura potrebbe apparire più sbiadita e meno morbida del previsto. Questi due errori non fanno una cosa giusta, ed è importante che lo spazio colore di lavoro sia lineare ("riferito alla scena") e che lo spazio di colore dell'output sia non lineare ("riferito alla visualizzazione").

## Ulteriori letture

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