color-management.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <!DOCTYPE html><html lang="fr"><head>
  2. <meta charset="utf-8">
  3. <title>Gestion des couleurs</title>
  4. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  5. <meta name="twitter:card" content="summary_large_image">
  6. <meta name="twitter:site" content="@threejs">
  7. <meta name="twitter:title" content="Three.js – Gestion des couleurs">
  8. <meta property="og:image" content="https://threejs.org/files/share.png">
  9. <link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
  10. <link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
  11. <link rel="stylesheet" href="../resources/lesson.css">
  12. <link rel="stylesheet" href="../resources/lang.css">
  13. <script type="importmap">
  14. {
  15. "imports": {
  16. "three": "../../build/three.module.js"
  17. }
  18. }
  19. </script>
  20. <style>
  21. blockquote {
  22. font-size: 0.8em;
  23. line-height: 1.5em;
  24. margin-left: 0;
  25. border-left: 4px solid #cccccc;
  26. padding: 1em 2em 1em 2em;
  27. }
  28. blockquote p:first-child {
  29. margin-top: 0;
  30. }
  31. blockquote p:last-child {
  32. margin-bottom: 0;
  33. }
  34. figure {
  35. width: 100%;
  36. margin: 1em 0;
  37. font-style: italic;
  38. }
  39. figure img {
  40. width: 100%;
  41. }
  42. figure.float {
  43. float: right;
  44. max-width: 30%;
  45. margin: 1em;
  46. }
  47. @media all and ( max-width: 640px ) {
  48. figure.float {
  49. float: none;
  50. max-width: 100%;
  51. }
  52. }
  53. </style>
  54. </head>
  55. <body>
  56. <div class="container">
  57. <div class="lesson-title">
  58. <h1>Gestion des couleurs</h1>
  59. </div>
  60. <div class="lesson">
  61. <div class="lesson-main">
  62. <h2>Qu'est-ce qu'un espace couleur ?</h2>
  63. <p>
  64. Chaque espace couleur est une collection de plusieurs décisions de conception, choisies ensemble pour prendre en charge une
  65. vaste gamme de couleurs tout en satisfaisant aux contraintes techniques liées à la précision et aux technologies
  66. d'affichage. Lors de la création d'un actif 3D, ou de l'assemblage d'actifs 3D dans une scène, il est
  67. important de connaître ces propriétés et la façon dont les propriétés d'un espace couleur sont liées
  68. aux autres espaces couleur de la scène.
  69. </p>
  70. <figure class="float">
  71. <img src="../resources/srgb_gamut.png" alt="">
  72. <figcaption>
  73. Couleurs sRGB et point blanc (D65) affichés dans le diagramme de chromaticité de référence CIE 1931.
  74. La région colorée représente une projection 2D du gamut sRGB, qui est un volume 3D.
  75. Source : <a href="https://en.wikipedia.org/wiki/SRGB" target="_blank" rel="noopener">Wikipedia</a>
  76. </figcaption>
  77. </figure>
  78. <ul>
  79. <li>
  80. <b>Primaires de couleur :</b> Les couleurs primaires (par exemple rouge, vert, bleu) ne sont pas absolues ; elles sont
  81. sélectionnées à partir du spectre visible en fonction des contraintes de précision limitée et des capacités des
  82. périphériques d'affichage disponibles. Les couleurs sont exprimées comme un ratio des couleurs primaires.
  83. </li>
  84. <li>
  85. <b>Point blanc :</b> La plupart des espaces couleur sont conçus de telle sorte qu'une somme pondérée égale des
  86. primaires <i>R = G = B</i> apparaisse sans couleur, ou "achromatique". L'apparence
  87. des valeurs achromatiques (comme le blanc ou le gris) dépend de la perception humaine, qui à son tour dépend
  88. fortement du contexte de l'observateur. Un espace couleur spécifie son "point blanc" pour équilibrer
  89. ces besoins. Le point blanc défini par l'espace couleur sRGB est
  90. [link:https://en.wikipedia.org/wiki/Illuminant_D65 D65].
  91. </li>
  92. <li>
  93. <b>Fonctions de transfert :</b> Après avoir choisi le gamut et un modèle de couleur, nous devons encore
  94. définir des correspondances ("fonctions de transfert") des valeurs numériques vers/depuis l'espace couleur. Est-ce que <i>r = 0.5</i>
  95. représente 50 % moins d'éclairage physique que <i>r = 1.0</i> ? Ou 50 % moins lumineux, tel que perçu
  96. par un œil humain moyen ? Ce sont des choses différentes, et cette différence peut être représentée par
  97. une fonction mathématique. Les fonctions de transfert peuvent être <i>linéaires</i> ou <i>non linéaires</i>, en fonction
  98. des objectifs de l'espace couleur. sRGB définit des fonctions de transfert non linéaires. Ces
  99. fonctions sont parfois approximées par des <i>fonctions gamma</i>, mais le terme "gamma" est
  100. ambigu et doit être évité dans ce contexte.
  101. </li>
  102. </ul>
  103. Ces trois paramètres — primaires de couleur, point blanc et fonctions de transfert — définissent un espace
  104. couleur, chacun choisi pour des objectifs particuliers. Ayant défini les paramètres, quelques termes supplémentaires
  105. sont utiles :
  106. <ul>
  107. <li>
  108. <b>Modèle de couleur :</b> Syntaxe pour identifier numériquement les couleurs dans le gamut choisi —
  109. un système de coordonnées pour les couleurs. Dans three.js, nous sommes principalement concernés par le modèle de couleur
  110. RGB, ayant trois coordonnées <i>r, g, b ∈ [0,1]</i> ("domaine fermé") ou
  111. <i>r, g, b ∈ [0,∞]</i> ("domaine ouvert") représentant chacune une fraction d'une couleur
  112. primaire. D'autres modèles de couleur (HSL, Lab, LCH) sont couramment utilisés pour le contrôle artistique.
  113. </li>
  114. <li>
  115. <b>Gamut de couleur :</b> Une fois que les primaires de couleur et un point blanc ont été choisis, ceux-ci représentent
  116. un volume dans le spectre visible (un "gamut"). Les couleurs ne se trouvant pas dans ce volume ("hors gamut")
  117. ne peuvent pas être exprimées par des valeurs RGB [0,1] en domaine fermé. Dans le domaine ouvert [0,∞], le gamut est
  118. techniquement infini.
  119. </li>
  120. </ul>
  121. <p>
  122. Considérez deux espaces couleur très courants : `SRGBColorSpace` ("sRGB") et
  123. `LinearSRGBColorSpace` ("Linear-sRGB"). Les deux utilisent les mêmes primaires et le même point blanc,
  124. et ont donc le même gamut de couleur. Les deux utilisent le modèle de couleur RGB. Ils ne diffèrent que par
  125. les fonctions de transfert — Linear-sRGB est linéaire par rapport à l'intensité lumineuse physique.
  126. sRGB utilise les fonctions de transfert sRGB non linéaires, et ressemble plus étroitement à la façon dont
  127. l'œil humain perçoit la lumière et à la réactivité des périphériques d'affichage courants.
  128. </p>
  129. <p>
  130. Cette différence est importante. Les calculs d'éclairage et autres opérations de rendu doivent
  131. généralement avoir lieu dans un espace couleur linéaire. Cependant, les couleurs linéaires sont moins efficaces pour
  132. être stockées dans une image ou un framebuffer, et ne paraissent pas correctes lorsqu'elles sont visualisées par un observateur humain.
  133. En conséquence, les textures d'entrée et l'image finale rendue utiliseront généralement l'espace couleur sRGB non linéaire.
  134. </p>
  135. <blockquote>
  136. <p>
  137. ℹ️ <i><b>AVIS :</b> Bien que certains écrans modernes prennent en charge des gamuts plus larges comme Display-P3,
  138. les API graphiques de la plateforme web reposent largement sur sRGB. Les applications utilisant three.js
  139. aujourd'hui utiliseront généralement uniquement les espaces couleur sRGB et Linear-sRGB.</i>
  140. </p>
  141. </blockquote>
  142. <h2>Rôles des espaces couleur</h2>
  143. <p>
  144. Les flux de travail linéaires — requis pour les méthodes de rendu modernes — impliquent généralement plus d'un
  145. espace couleur, chacun assigné à un rôle particulier. Les espaces couleur linéaires et non linéaires sont
  146. appropriés pour différents rôles, expliqués ci-dessous.
  147. </p>
  148. <h3>Espace couleur d'entrée</h3>
  149. <p>
  150. Les couleurs fournies à three.js — à partir de sélecteurs de couleur, de textures, de modèles 3D et d'autres sources —
  151. ont chacune un espace couleur associé. Celles qui ne sont pas déjà dans l'espace couleur de travail Linear-sRGB
  152. doivent être converties, et les textures doivent recevoir l'affectation correcte <i>texture.colorSpace</i>.
  153. Certaines conversions (pour les couleurs hexadécimales et CSS en sRGB) peuvent être effectuées automatiquement si
  154. l'API THREE.ColorManagement est activée avant l'initialisation des couleurs :
  155. </p>
  156. <code>
  157. THREE.ColorManagement.enabled = true;
  158. </code>
  159. <p>
  160. THREE.ColorManagement est activé par défaut.
  161. </p>
  162. <ul>
  163. <li>
  164. <b>Matériaux, lumières et shaders :</b> Les couleurs dans les matériaux, les lumières et les shaders stockent
  165. les composants RGB dans l'espace couleur de travail Linear-sRGB.
  166. </li>
  167. <li>
  168. <b>Couleurs de sommet :</b> `BufferAttribute` stockent les composants RGB dans l'espace couleur de travail
  169. Linear-sRGB.
  170. </li>
  171. <li>
  172. <b>Textures de couleur :</b> Les `Texture` PNG ou JPEG contenant des informations de couleur
  173. (comme .map ou .emissiveMap) utilisent l'espace couleur sRGB en domaine fermé, et doivent être annotées avec
  174. <i>texture.colorSpace = SRGBColorSpace</i>. Des formats comme OpenEXR (parfois utilisés pour .envMap ou
  175. .lightMap) utilisent l'espace couleur Linear-sRGB indiqué par <i>texture.colorSpace = LinearSRGBColorSpace</i>,
  176. et peuvent contenir des valeurs dans le domaine ouvert [0,∞].
  177. </li>
  178. <li>
  179. <b>Textures non couleur :</b> Les textures qui ne stockent pas d'informations de couleur (comme .normalMap
  180. ou .roughnessMap) n'ont pas d'espace couleur associé, et utilisent généralement l'annotation de texture (par défaut) de
  181. <i>texture.colorSpace = NoColorSpace</i>. Dans de rares cas, les données non couleur
  182. peuvent être représentées avec d'autres encodages non linéaires pour des raisons techniques.
  183. </li>
  184. </ul>
  185. <blockquote>
  186. <p>
  187. ⚠️ <i><b>AVERTISSEMENT :</b> De nombreux formats de modèles 3D ne définissent pas correctement ou de manière cohérente
  188. les informations d'espace couleur. Bien que three.js tente de gérer la plupart des cas, les problèmes
  189. sont fréquents avec les anciens formats de fichiers. Pour de meilleurs résultats, utilisez glTF 2.0 (`GLTFLoader`)
  190. et testez les modèles 3D dans des visualiseurs en ligne tôt pour confirmer que l'actif lui-même est correct.</i>
  191. </p>
  192. </blockquote>
  193. <h3>Espace couleur de travail</h3>
  194. <p>
  195. Le rendu, l'interpolation et de nombreuses autres opérations doivent être effectuées dans un espace couleur de travail
  196. linéaire en domaine ouvert, dans lequel les composants RGB sont proportionnels à l'illumination physique.
  197. Dans three.js, l'espace couleur de travail est Linear-sRGB.
  198. </p>
  199. <h3>Espace couleur de sortie</h3>
  200. <p>
  201. La sortie vers un périphérique d'affichage, une image ou une vidéo peut impliquer une conversion de l'espace couleur de travail
  202. Linear-sRGB en domaine ouvert vers un autre espace couleur. La conversion est définie par
  203. (`WebGLRenderer.outputColorSpace`). Lors de l'utilisation du post-traitement, cela nécessite OutputPass.
  204. </p>
  205. <ul>
  206. <li>
  207. <b>Affichage :</b> Les couleurs écrites sur un canevas WebGL pour l'affichage doivent être dans l'espace
  208. couleur sRGB.
  209. </li>
  210. <li>
  211. <b>Image :</b> Les couleurs écrites dans une image doivent utiliser l'espace couleur approprié pour
  212. le format et l'utilisation. Les images entièrement rendues écrites dans des textures PNG ou JPEG utilisent généralement
  213. l'espace couleur sRGB. Les images contenant de l'émission, des lightmaps ou d'autres données non confinées à la plage [0,1]
  214. utiliseront généralement l'espace couleur Linear-sRGB en domaine ouvert, et un format d'image compatible comme OpenEXR.
  215. </li>
  216. </ul>
  217. <blockquote>
  218. <p>
  219. ⚠️ <i><b>AVERTISSEMENT :</b> Les cibles de rendu peuvent utiliser soit sRGB soit Linear-sRGB. sRGB utilise
  220. mieux la précision limitée. Dans le domaine fermé, 8 bits suffisent souvent pour sRGB tandis que ≥12 bits
  221. (half float) peuvent être nécessaires pour Linear-sRGB. Si les étapes ultérieures du pipeline nécessitent
  222. une entrée Linear-sRGB, les conversions supplémentaires peuvent entraîner un léger coût de performance.</i>
  223. </p>
  224. </blockquote>
  225. <p>
  226. Les matériaux personnalisés basés sur `ShaderMaterial` et `RawShaderMaterial` doivent implémenter leur propre conversion d'espace couleur de sortie.
  227. Pour les instances de `ShaderMaterial`, ajouter le chunk de shader `colorspace_fragment` à la fonction `main()` du shader de fragment devrait être suffisant.
  228. </p>
  229. <h2>Utilisation des instances THREE.Color</h2>
  230. <p>
  231. Les méthodes lisant ou modifiant des instances `Color` supposent que les données sont déjà dans
  232. l'espace couleur de travail de three.js, Linear-sRGB. Les composants RGB et HSL sont des
  233. représentations directes des données stockées par l'instance Color, et ne sont jamais convertis
  234. implicitement. Les données de couleur peuvent être explicitement converties avec <i>.convertLinearToSRGB()</i>
  235. ou <i>.convertSRGBToLinear()</i>.
  236. </p>
  237. <pre class="prettyprint notranslate lang-js" translate="no">
  238. // RGB components (no change).
  239. color.r = color.g = color.b = 0.5;
  240. console.log( color.r ); // → 0.5
  241. // Manual conversion.
  242. color.r = 0.5;
  243. color.convertSRGBToLinear();
  244. console.log( color.r ); // → 0.214041140
  245. </pre>
  246. <p>
  247. Avec <i>ColorManagement.enabled = true</i> (recommandé), certaines conversions
  248. sont effectuées automatiquement. Comme les couleurs hexadécimales et CSS sont généralement sRGB, les méthodes `Color`
  249. convertiront automatiquement ces entrées de sRGB vers Linear-sRGB dans les setters, ou convertiront de
  250. Linear-sRGB vers sRGB lors du retour d'une sortie hexadécimale ou CSS à partir des getters.
  251. </p>
  252. <pre class="prettyprint notranslate lang-js" translate="no">
  253. // Hexadecimal conversion.
  254. color.setHex( 0x808080 );
  255. console.log( color.r ); // → 0.214041140
  256. console.log( color.getHex() ); // → 0x808080
  257. // CSS conversion.
  258. color.setStyle( 'rgb( 0.5, 0.5, 0.5 )' );
  259. console.log( color.r ); // → 0.214041140
  260. // Override conversion with 'colorSpace' argument.
  261. color.setHex( 0x808080, LinearSRGBColorSpace );
  262. console.log( color.r ); // → 0.5
  263. console.log( color.getHex( LinearSRGBColorSpace ) ); // → 0x808080
  264. console.log( color.getHex( SRGBColorSpace ) ); // → 0xBCBCBC
  265. </pre>
  266. <h2>Erreurs courantes</h2>
  267. <p>
  268. Lorsqu'une couleur ou une texture individuelle est mal configurée, elle apparaîtra plus foncée ou plus claire que
  269. prévu. Lorsque l'espace couleur de sortie du renderer est mal configuré, toute la scène peut apparaître
  270. plus foncée (par exemple, conversion manquante vers sRGB) ou plus claire (par exemple, une double conversion vers sRGB avec
  271. post-traitement). Dans chaque cas, le problème peut ne pas être uniforme, et simplement augmenter/diminuer
  272. l'éclairage ne le résout pas.
  273. </p>
  274. <p>
  275. Un problème plus subtil apparaît lorsque <i>à la fois</i> les espaces couleur d'entrée et les espaces couleur de sortie
  276. sont incorrects — les niveaux de luminosité globaux peuvent être corrects, mais les couleurs peuvent changer
  277. de manière inattendue sous différents éclairages, ou l'ombrage peut sembler plus brûlé et moins doux
  278. que prévu. Ces deux erreurs ne font pas une seule bonne chose, et il est important que l'espace
  279. couleur de travail soit linéaire ("référé à la scène") et l'espace couleur de sortie soit non linéaire
  280. ("référé à l'affichage").
  281. </p>
  282. <h2>Pour aller plus loin</h2>
  283. <ul>
  284. <li>
  285. <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>, par Larry Gritz et Eugene d'Eon
  286. </li>
  287. <li>
  288. <a href="https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/" target="_blank" rel="noopener">Ce que chaque programmeur devrait savoir sur le gamma</a>, par John Novak
  289. </li>
  290. <li>
  291. <a href="https://hg2dc.com/" target="_blank" rel="noopener">Le guide du routard de la couleur numérique</a>, par Troy Sobotka
  292. </li>
  293. <li>
  294. <a href="https://docs.blender.org/manual/en/latest/render/color_management.html" target="_blank" rel="noopener">Gestion des couleurs</a>, Blender
  295. </li>
  296. </ul>
  297. </div>
  298. </div>
  299. </div>
  300. <script src="../resources/prettify.js"></script>
  301. <script src="../resources/lesson.js"></script>
  302. </body></html>
粤ICP备19079148号