|
@@ -0,0 +1,417 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="en">
|
|
|
+ <head>
|
|
|
+ <meta charset="utf-8" />
|
|
|
+ <base href="../../../" />
|
|
|
+ <script src="page.js"></script>
|
|
|
+ <link type="text/css" rel="stylesheet" href="page.css" />
|
|
|
+ <style>
|
|
|
+ blockquote {
|
|
|
+ font-size: 0.8em;
|
|
|
+ line-height: 1.5em;
|
|
|
+ margin-left: 0;
|
|
|
+ border-left: 4px solid #cccccc;
|
|
|
+ padding: 1em 2em 1em 2em;
|
|
|
+ }
|
|
|
+
|
|
|
+ blockquote p:first-child {
|
|
|
+ margin-top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ blockquote p:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ figure {
|
|
|
+ width: 100%;
|
|
|
+ margin: 1em 0;
|
|
|
+ font-style: italic;
|
|
|
+ }
|
|
|
+
|
|
|
+ figure img {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ figure.float {
|
|
|
+ float: right;
|
|
|
+ max-width: 30%;
|
|
|
+ margin: 1em;
|
|
|
+ }
|
|
|
+
|
|
|
+ @media all and (max-width: 640px) {
|
|
|
+ figure.float {
|
|
|
+ float: none;
|
|
|
+ max-width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+
|
|
|
+ <body>
|
|
|
+ <h1>Gestione del colore ([name])</h1>
|
|
|
+
|
|
|
+ <h2>Cos'è lo spazio colore?</h2>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <figure class="float">
|
|
|
+ <img src="resources/srgb_gamut.png" alt="" />
|
|
|
+ <figcaption>
|
|
|
+ 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:
|
|
|
+ <a
|
|
|
+ href="https://en.wikipedia.org/wiki/SRGB"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener"
|
|
|
+ >Wikipedia</a
|
|
|
+ >
|
|
|
+ </figcaption>
|
|
|
+ </figure>
|
|
|
+
|
|
|
+ <ul>
|
|
|
+ <li>
|
|
|
+ <b>Colori primari:</b> 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.
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Punto di bianco:</b> La maggior parte degli spazi colore è progettata
|
|
|
+ in modo tale che una somma equamente ponderata di primari
|
|
|
+ <i>R = G = B</i> 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 è
|
|
|
+ <a href="https://en.wikipedia.org/wiki/Illuminant_D65" target="_blank"
|
|
|
+ >D65</a
|
|
|
+ >.
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Funzioni di trasferimento (transfer functions):</b> 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 <i>r = 1,0</i>? 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 <i>lineari</i> o
|
|
|
+ <i>non lineari</i>, a seconda degli obiettivi dello spazio colore. sRGB
|
|
|
+ definisce funzioni di trasferimento non lineari. Queste funzioni sono
|
|
|
+ talvolta approssimate come <i>funzioni gamma</i>, ma il termine "gamma"
|
|
|
+ è ambiguo e dovrebbe essere evitato in questo contesto.
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+
|
|
|
+ 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:
|
|
|
+
|
|
|
+ <ul>
|
|
|
+ <li>
|
|
|
+ <b>Modello di colore:</b> 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
|
|
|
+ <i>r, g, b ∈ [0,1]</i> ("dominio chiuso") o
|
|
|
+ <i>r, g, b ∈ [0,∞]</i> ("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.
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Gamma di colori:</b> 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.
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <blockquote>
|
|
|
+ <p>
|
|
|
+ ℹ️
|
|
|
+ <i
|
|
|
+ ><b>ATTENZIONE:</b> 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.
|
|
|
+ </i>
|
|
|
+ </p>
|
|
|
+ </blockquote>
|
|
|
+
|
|
|
+ <h2>Ruoli degli spazi colore</h2>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <h3>Input color space</h3>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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
|
|
|
+ <i>texture.encoding</i>. 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:
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <code> THREE.ColorManagement.legacyMode = false; </code>
|
|
|
+
|
|
|
+ <ul>
|
|
|
+ <li>
|
|
|
+ <b>Materiali, luci, e shader:</b> I colori nei materiali, nelle luci e
|
|
|
+ negli shader memorizzano i componenti RGB nello spazio colore di lavoro
|
|
|
+ Linear-sRGB.
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Colori dei vertici:</b> [page:BufferAttribute BufferAttributes]
|
|
|
+ memorizza i componenti RGB nello spazio colore di lavoro Linear-sRGB.
|
|
|
+ </li>
|
|
|
+
|
|
|
+ <li>
|
|
|
+ <b>Colori delle texture:</b> 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
|
|
|
+ <i>texture.encoding = sRGBEncoding</i>. I formati come OpenEXR (a volte
|
|
|
+ usati per .envMap o .lightMap) utilizzano lo spazio colore Linear-sRGB
|
|
|
+ indicato con <i>texture.encoding = LinearEncoding</i>, e possono
|
|
|
+ contenere valori nel dominio aperto [0,∞].
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Texture non a colori:</b> 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)
|
|
|
+ <i>texture.encoding = LinearEncoding</i>. In rari casi, i dati non a
|
|
|
+ colori possono essere rappresentati con altre codifiche non lineari per
|
|
|
+ motivi tecnici.
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+
|
|
|
+ <blockquote>
|
|
|
+ <p>
|
|
|
+ ⚠️
|
|
|
+ <i
|
|
|
+ ><b>ATTENZIONE:</b> [page:Scene.fog], [page:Scene.background], e
|
|
|
+ [page:WebGLRenderer.setClearColor] sono eccezioni alla regola. Queste
|
|
|
+ proprietà non sono interessate da [page:WebGLRenderer.outputEncoding]
|
|
|
+ e quindi devono memorizzare i componenti RGB nello spazio colore di
|
|
|
+ <u>output</u> del renderer.</i
|
|
|
+ >
|
|
|
+ </p>
|
|
|
+ </blockquote>
|
|
|
+
|
|
|
+ <blockquote>
|
|
|
+ <p>
|
|
|
+ ⚠️
|
|
|
+ <i
|
|
|
+ ><b>ATTENZIONE:</b> 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.
|
|
|
+ </i>
|
|
|
+ </p>
|
|
|
+ </blockquote>
|
|
|
+
|
|
|
+ <h3>Spazio colore di lavoro</h3>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <h3>Output color space</h3>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.outputEncoding]), o durante il post-processing.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <code>
|
|
|
+ renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing
|
|
|
+ </code>
|
|
|
+
|
|
|
+ <ul>
|
|
|
+ <li>
|
|
|
+ <b>Display:</b> I colori scritti in un canvas WebGL per i display devono
|
|
|
+ essere nello spazio colore sRGB.
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <b>Immagine:</b> 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.
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+
|
|
|
+ <blockquote>
|
|
|
+ <p>
|
|
|
+ ⚠️
|
|
|
+ <i
|
|
|
+ ><b>ATTENZIONE:</b> 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.</i
|
|
|
+ >
|
|
|
+ </p>
|
|
|
+ </blockquote>
|
|
|
+
|
|
|
+ <h2>Lavorare con le istanze di THREE.Color</h2>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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
|
|
|
+ <i>.convertLinearToSRGB()</i> o <i>.convertSRGBToLinear()</i>.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <code>
|
|
|
+ // 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
|
|
|
+ </code>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ Con <i>ColorManagement.legacyMode = false</i> 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <code>
|
|
|
+ // 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
|
|
|
+ </code>
|
|
|
+
|
|
|
+ <h2>Errori comuni</h2>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ 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.
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <p>
|
|
|
+ Un problema più sottile si verifica quando <i>entrambi</i> 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").
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <h2>Ulteriori letture</h2>
|
|
|
+
|
|
|
+ <ul>
|
|
|
+ <li>
|
|
|
+ <a
|
|
|
+ href="https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener"
|
|
|
+ >GPU Gems 3: The Importance of Being Linear</a
|
|
|
+ >, di Larry Gritz and Eugene d'Eon
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <a
|
|
|
+ href="https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener"
|
|
|
+ >What every coder should know about gamma</a
|
|
|
+ >, di John Novak
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <a href="https://hg2dc.com/" target="_blank" rel="noopener"
|
|
|
+ >The Hitchhiker's Guide to Digital Color</a
|
|
|
+ >, di Troy Sobotka
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <a
|
|
|
+ href="https://docs.blender.org/manual/en/latest/render/color_management.html"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener"
|
|
|
+ >Color Management</a
|
|
|
+ >, Blender
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </body>
|
|
|
+</html>
|