Color-management.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <!DOCTYPE html>
  2. <html lang="it">
  3. <head>
  4. <meta charset="utf-8" />
  5. <base href="../../../" />
  6. <script src="page.js"></script>
  7. <link type="text/css" rel="stylesheet" href="page.css" />
  8. <style>
  9. blockquote {
  10. font-size: 0.8em;
  11. line-height: 1.5em;
  12. margin-left: 0;
  13. border-left: 4px solid #cccccc;
  14. padding: 1em 2em 1em 2em;
  15. }
  16. blockquote p:first-child {
  17. margin-top: 0;
  18. }
  19. blockquote p:last-child {
  20. margin-bottom: 0;
  21. }
  22. figure {
  23. width: 100%;
  24. margin: 1em 0;
  25. font-style: italic;
  26. }
  27. figure img {
  28. width: 100%;
  29. }
  30. figure.float {
  31. float: right;
  32. max-width: 30%;
  33. margin: 1em;
  34. }
  35. @media all and (max-width: 640px) {
  36. figure.float {
  37. float: none;
  38. max-width: 100%;
  39. }
  40. }
  41. </style>
  42. </head>
  43. <body>
  44. <h1>Gestione del colore ([name])</h1>
  45. <h2>Cos'è lo spazio colore?</h2>
  46. <p>
  47. Ogni spazio colore è una collezione di diverse decisioni progettuali,
  48. scelte insieme per supportare un'ampia gamma di colori e al contempo
  49. soddisfare i vincoli tecnici legati alla precisione e alle tecnologie di
  50. visualizzazione. Quando si crea una risorsa 3D, o si assemblano delle
  51. risorse 3D insieme in una scena, è importante sapere quali sono queste
  52. proprietà e come le proprietà di uno spazio colore si relazionano con
  53. altri spazi colore nella scena.
  54. </p>
  55. <figure class="float">
  56. <img src="resources/srgb_gamut.png" alt="" />
  57. <figcaption>
  58. Colori sRGB e il punto di bianco (D65) visualizzati nel diagramma
  59. cromatico di riferimento CIE 1931. La regione colorata rappresenta una
  60. proiezione 2D della gamma sRGB, che è un volume 3D. Fonte:
  61. <a
  62. href="https://en.wikipedia.org/wiki/SRGB"
  63. target="_blank"
  64. rel="noopener"
  65. >Wikipedia</a
  66. >
  67. </figcaption>
  68. </figure>
  69. <ul>
  70. <li>
  71. <b>Colori primari:</b> I colori primari (rosso, verde, blu) non sono
  72. assoluti; vengono selezionati dallo spettro visibile in base ai vincoli
  73. di precisione limitata e alla capacità dei dispositivi di
  74. visualizzazione disponibili. I colori sono espressi come rapporto tra i
  75. colori primari.
  76. </li>
  77. <li>
  78. <b>Punto di bianco:</b> La maggior parte degli spazi colore è progettata
  79. in modo tale che una somma equamente ponderata di primari
  80. <i>R = G = B</i> appaia priva di colore o "acromatica". L'aspetto dei
  81. valori cromatici (come il bianco o il grigio) dipende dalla percezione
  82. umana, che a sua volta dipende fortemente dal contesto dell'osservatore.
  83. Uno spazio colore specifica il suo "punto di bianco" per bilanciare
  84. queste esigenze. Il punto di bianco definito dallo spazio colore sRGB è
  85. <a href="https://en.wikipedia.org/wiki/Illuminant_D65" target="_blank"
  86. >D65</a
  87. >.
  88. </li>
  89. <li>
  90. <b>Funzioni di trasferimento (transfer functions):</b> Dopo aver scelto
  91. la gamma cromatica e un modello di colore, dobbiamo ancora definire le
  92. mappature ("funzioni di trasferimento") dei valori numerici da/verso lo
  93. spazio colore. R = 0,5 rappresenta il 50% in meno di illuminazione
  94. fisica rispetto a <i>r = 1,0</i>? O il 50% in meno di luminosità, come
  95. percepito da un occhio umano medio? Sono cose diverse e questa
  96. differenza può essere rappresentata come una funzione matematica. Le
  97. funzioni di trasferimento possono essere <i>lineari</i> o
  98. <i>non lineari</i>, a seconda degli obiettivi dello spazio colore. sRGB
  99. definisce funzioni di trasferimento non lineari. Queste funzioni sono
  100. talvolta approssimate come <i>funzioni gamma</i>, ma il termine "gamma"
  101. è ambiguo e dovrebbe essere evitato in questo contesto.
  102. </li>
  103. </ul>
  104. Questi tre parametri - colori primari, punto di bianco e funzioni di
  105. trasferimento - definiscono uno spazio colore, ognuno scelto per obiettivi
  106. specifici. Dopo aver definito i parametri, sono utili alcuni termini
  107. aggiuntivi:
  108. <ul>
  109. <li>
  110. <b>Modello di colore:</b> Sintassi per identificare numericamente i
  111. colori all'interno della gamma cromatica scelta - un sistema di
  112. coordinate per i colori. In three.js ci occupiamo principalmente del
  113. modello di colore RGB, con tre coordinate
  114. <i>r, g, b ∈ [0,1]</i> ("dominio chiuso") o
  115. <i>r, g, b ∈ [0,∞]</i> ("dominio aperto") che rappresentano ciascuna una
  116. frazione di un colore primario. Altri modelli di colore (HSL, Lab, LCH)
  117. sono comunemente utilizzati per il controllo artistico.
  118. </li>
  119. <li>
  120. <b>Gamma di colori:</b> Quando i colori primari e il punto di bianco
  121. sono stati scelti, questi rappresentano un volume all'interno dello
  122. spettro visibile (un "gamut"). I colori che non rientrano in questo
  123. volume ("fuori gamut") non possono essere espressi dai valori RGB del
  124. dominio chiuso [0,1]. Nel dominio aperto [0,∞], il gamut è tecnicamente
  125. infinito.
  126. </li>
  127. </ul>
  128. <p>
  129. Consideriamo due spazi colori comuni: [page:SRGBColorSpace] ("sRGB") e
  130. [page:LinearSRGBColorSpace] ("Linear-sRGB"). Entrambi usano gli stessi
  131. colori primari e lo stesso punto di bianco, e quindi hanno la stessa gamma
  132. di colori. Entrambi utilizzano il modello di colore RGB. Sono diversi solo
  133. nelle funzioni di trasferimento - Linear-sRGB è lineare rispetto
  134. all'intensità della luce fisica, mentre sRGB utilizza le funzioni di
  135. trasferimento non lineari di sRGB e si avvicina maggiormente al modo in
  136. cui l'occhio umano percepisce la luce e alla reattività dei comuni
  137. dispositivi di visualizzazione.
  138. </p>
  139. <p>
  140. Questa differenza è importante. I calcoli di illuminazione e altre
  141. operazioni di rendering devono generalmente avvenire in uno spazio di
  142. colore lineare. Tuttavia, i colori lineari sono meno efficienti da
  143. memorizzare in un'immagine o in un framebuffer e non hanno un aspetto
  144. corretto quando vengono osservati da un osservatore umano. Di conseguenza,
  145. le texture di input e l'immagine finale renderizzata utilizzano
  146. generalmente lo spazio di colore sRGB non lineare.
  147. </p>
  148. <blockquote>
  149. <p>
  150. ℹ️
  151. <i
  152. ><b>ATTENZIONE:</b> Anche se alcuni display moderni supportano gamme
  153. più ampie come Display-P3, le API grafiche della piattaforma web si
  154. basano in gran parte su sRGB. Le applicazioni che utilizzano three.js
  155. oggi utilizzano in genere solo gli spazi colore sRGB e Linear-sRGB.
  156. </i>
  157. </p>
  158. </blockquote>
  159. <h2>Ruoli degli spazi colore</h2>
  160. <p>
  161. Un flusso di lavoro lineare - richiesto per moderni metodi di rendering -
  162. generalmente coinvolge più di uno spazio di colore, ognuno assegnato ad un
  163. ruolo specifico. Spazi colore lineari o non lineari sono adatti a ruoli
  164. diversi, come spiegato di seguito.
  165. </p>
  166. <h3>Input color space</h3>
  167. <p>
  168. I colori forniti a three.js - dai color picker, dalle texture, dai modelli
  169. 3D e da altre risorse - hanno ciascuno uno spazio colore associato. Quelli
  170. che non sono già nello spazio colore di lavoro Linear-sRGB devono essere
  171. convertiti e alle texture deve essere assegnata la corretta assegnazione
  172. <i>texture.encoding</i>. Alcune conversioni (per i colori esadecimali e
  173. CSS in sRGB) possono essere effettuate automaticamente se la modalità di
  174. gestione del colore legacy è disabilitata prima dell'inizializzazione dei
  175. colori:
  176. </p>
  177. <code> THREE.ColorManagement.legacyMode = false; </code>
  178. <ul>
  179. <li>
  180. <b>Materiali, luci, e shader:</b> I colori nei materiali, nelle luci e
  181. negli shader memorizzano i componenti RGB nello spazio colore di lavoro
  182. Linear-sRGB.
  183. </li>
  184. <li>
  185. <b>Colori dei vertici:</b> [page:BufferAttribute BufferAttributes]
  186. memorizza i componenti RGB nello spazio colore di lavoro Linear-sRGB.
  187. </li>
  188. <li>
  189. <b>Colori delle texture:</b> Le [page:Texture Texture] PNG o JPEG
  190. contenti informazioni sul colore (come .map o .emissiveMap) usano lo
  191. spazio colore sRGB a dominio chiuso, e devono essere annotate con
  192. <i>texture.encoding = sRGBEncoding</i>. I formati come OpenEXR (a volte
  193. usati per .envMap o .lightMap) utilizzano lo spazio colore Linear-sRGB
  194. indicato con <i>texture.encoding = LinearEncoding</i>, e possono
  195. contenere valori nel dominio aperto [0,∞].
  196. </li>
  197. <li>
  198. <b>Texture non a colori:</b> Le texture che non memorizzano informazioni
  199. relative ai colori (come .normalMap o .roughnessMap) non hanno associato
  200. uno spazio colore, e generalmente usano l'annotazione (predefinita)
  201. <i>texture.encoding = LinearEncoding</i>. In rari casi, i dati non a
  202. colori possono essere rappresentati con altre codifiche non lineari per
  203. motivi tecnici.
  204. </li>
  205. </ul>
  206. <blockquote>
  207. <p>
  208. ⚠️
  209. <i
  210. ><b>ATTENZIONE:</b> [page:Scene.fog], [page:Scene.background], e
  211. [page:WebGLRenderer.setClearColor] sono eccezioni alla regola. Queste
  212. proprietà non sono interessate da [page:WebGLRenderer.outputEncoding]
  213. e quindi devono memorizzare i componenti RGB nello spazio colore di
  214. <u>output</u> del renderer.</i
  215. >
  216. </p>
  217. </blockquote>
  218. <blockquote>
  219. <p>
  220. ⚠️
  221. <i
  222. ><b>ATTENZIONE:</b> Molti formati per modelli 3D non definiscono
  223. correttamente o in modo coerente le informazioni sullo spazio colore.
  224. Sebbene three.js tenti di gestire la maggior parte dei casi, i
  225. problemi sono spesso con i file con formati meno recenti. Per ottenere
  226. un miglior risultato bisogna utilizzare il formato glTF 2.0
  227. ([page:GLTFLoader]) e prima bisogna testare i modelli 3D in
  228. visualizzatori online per confermare che la risorsa stessa sia
  229. corretta.
  230. </i>
  231. </p>
  232. </blockquote>
  233. <h3>Spazio colore di lavoro</h3>
  234. <p>
  235. Rendering, interpolazione e molte altre operazioni devono essere eseguite
  236. in uno spazio colore di lavoro lineare, nel quale i componenti RGB sono
  237. proporzionali all'illuminazione fisica. In three.js, lo spazio colore di
  238. lavoro è Linear-sRGB.
  239. </p>
  240. <h3>Output color space</h3>
  241. <p>
  242. L'output su un dispositivo di visualizzazione, a un'immagine o a un video,
  243. può comportare la conversione dallo spazio colore di lavoro Linear-sRGB di
  244. dominio aperto a un altro spazio di colore. Questa conversione può essere
  245. eseguita nel passaggio di rendering principale
  246. ([page:WebGLRenderer.outputEncoding]), o durante il post-processing.
  247. </p>
  248. <code>
  249. renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing
  250. </code>
  251. <ul>
  252. <li>
  253. <b>Display:</b> I colori scritti in un canvas WebGL per i display devono
  254. essere nello spazio colore sRGB.
  255. </li>
  256. <li>
  257. <b>Immagine:</b> I colori scritti su un'immagine devono utilizzare lo
  258. spazio colore appropriato per il formato e per il suo uso. Le immagini
  259. completamente renderizzate scritte per texture PNG o JPEG generalmente
  260. usano lo spazio colore sRGB. Immagini contenenti emissioni, mappe di
  261. luce, o altri dati non limitati all'intervallo [0,1] utilizzaranno
  262. generalmente lo spazio colore Linear-sRGB a dominio aperto, e un formato
  263. immagine compatibile come OpenEXR.
  264. </li>
  265. </ul>
  266. <blockquote>
  267. <p>
  268. ⚠️
  269. <i
  270. ><b>ATTENZIONE:</b> I target di rendering possono utilizzare sia sRGB
  271. che Linear-sRGB. sRGB utilizza meglio la precisione limitata. Nel
  272. dominio chiuso, 8 bit sono sufficienti per sRGB mentre ≥12 (mezzo
  273. float) possono essere richiesti per Linear-sRGB. Se gli stadi
  274. successivi delle pipeline richiedono un ingresso Linear-sRGB, le
  275. conversioni aggiuntive possono avere un piccolo costo in termini di
  276. prestazioni.</i
  277. >
  278. </p>
  279. </blockquote>
  280. <h2>Lavorare con le istanze di THREE.Color</h2>
  281. <p>
  282. I metodi di lettura o modifica delle istanze [page:Color] presuppongono
  283. che i dati siano già nello spazio colore di lavoro di three.js,
  284. Linear-sRGB. I componenti RGB e HSL sono rappresentazioni dirette dei dati
  285. memorizzati dall'istanza Color, e non sono mai convertiti implicitamente.
  286. I dati di Color possono essere esplicitamenre convertiti con
  287. <i>.convertLinearToSRGB()</i> o <i>.convertSRGBToLinear()</i>.
  288. </p>
  289. <code>
  290. // RGB components (no change).
  291. color.r = color.g = color.b = 0.5;
  292. console.log( color.r ); // → 0.5
  293. // Manual conversion.
  294. color.r = 0.5;
  295. color.convertSRGBToLinear();
  296. console.log( color.r ); // → 0.214041140
  297. </code>
  298. <p>
  299. Con <i>ColorManagement.legacyMode = false</i> impostato (consigliato),
  300. alcune conversioni vengono effettuate automaticamente. Poiché i colori
  301. esadecimali e CSS sono generalmente sRGB, i metodi [page:Color]
  302. convertiranno automaticamente questi input da sRGB a Linear-sRGB nei
  303. setter, oppure convertiranno da Linear-sRGB a sRGB quando restituiscono
  304. output esadecimali o CSS dai getter.
  305. </p>
  306. <code>
  307. // Hexadecimal conversion.
  308. color.setHex( 0x808080 );
  309. console.log( color.r ); // → 0.214041140
  310. console.log( color.getHex() ); // → 0x808080
  311. // CSS conversion.
  312. color.setStyle( 'rgb( 0.5, 0.5, 0.5 )' );
  313. console.log( color.r ); // → 0.214041140
  314. // Override conversion with 'colorSpace' argument.
  315. color.setHex( 0x808080, LinearSRGBColorSpace );
  316. console.log( color.r ); // → 0.5
  317. console.log( color.getHex( LinearSRGBColorSpace ) ); // → 0x808080
  318. console.log( color.getHex( SRGBColorSpace ) ); // → 0xBCBCBC
  319. </code>
  320. <h2>Errori comuni</h2>
  321. <p>
  322. Quando un singolo colore o una texture non sono configurati correttamente,
  323. apparirà più scuro o più chiaro del previsto. Quando lo spazio colore di
  324. output del renderer non è configurato correttamente, l'intera scena
  325. potrebbe essere più scura (ad es. manca la conversione ad sRGB) o più
  326. chiara (ad es. una doppia conversione a sRGB con post-processing). In ogni
  327. caso il problema potrebbe non essere uniforme e semplicemente
  328. aumentare/dimunire la luminosità non lo risolverebbe.
  329. </p>
  330. <p>
  331. Un problema più sottile si verifica quando <i>entrambi</i> lo spazio colore di
  332. input e quello di output non sono corretti - i livelli di luminosità complessivi
  333. potrebbero andare bene, ma i colori potrebbero cambiare in modo imprevisto in
  334. condizioni di illuminazione diversa o l'ombreggiatura potrebbe apparire più sbiadita
  335. e meno morbida del previsto. Questi due errori non fanno una cosa giusta, ed è importante
  336. che lo spazio colore di lavoro sia lineare ("riferito alla scena") e che lo spazio di colore
  337. dell'output sia non lineare ("riferito alla visualizzazione").
  338. </p>
  339. <h2>Ulteriori letture</h2>
  340. <ul>
  341. <li>
  342. <a
  343. href="https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear"
  344. target="_blank"
  345. rel="noopener"
  346. >GPU Gems 3: The Importance of Being Linear</a
  347. >, di Larry Gritz and Eugene d'Eon
  348. </li>
  349. <li>
  350. <a
  351. href="https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/"
  352. target="_blank"
  353. rel="noopener"
  354. >What every coder should know about gamma</a
  355. >, di John Novak
  356. </li>
  357. <li>
  358. <a href="https://hg2dc.com/" target="_blank" rel="noopener"
  359. >The Hitchhiker's Guide to Digital Color</a
  360. >, di Troy Sobotka
  361. </li>
  362. <li>
  363. <a
  364. href="https://docs.blender.org/manual/en/latest/render/color_management.html"
  365. target="_blank"
  366. rel="noopener"
  367. >Color Management</a
  368. >, Blender
  369. </li>
  370. </ul>
  371. </body>
  372. </html>