LoginSignup
2
3

先に結論だけ

Three.js r165において

  • WebGPURendererではoutputColorSpaceはMaterialの透明度に対して影響を与えます
  • WebGLRendererではoutputColorSpaceを変更してもMaterialの透明度は影響されません

WebGPURendererでWebGLRendererと同じようにMaterialの透明度を扱いたい場合は、Colorクラスの変換関数を利用しましょう。

はじめに

この記事は、Three.js r165のWebGPURendererにおいて、outputColorSpaceとMaterialの透明度の関係性について調査した結果をまとめたものです。

対象とする読者

  • Three.jsを使用している方
  • WebGPURendererを使用しているか、使用する予定がある

対象とする環境

  • Three.js r165
  • Chrome v126.0.6478.63

この記事は、Three.js r165での挙動について記載しています。将来のバージョンでは挙動が変わるかもしれないので、記事を読む前にお手元の環境のバージョンを確認してください。

この記事で問題とする症状

WebGPURendererで、Materialのtransparentをtrue、opacityを0.2程度に設定すると、WebGLRendererよりも明るく表示される症状が発生しました。

この症状が発生する原因を調査し、解決策を見つけることがこの記事の目的です。

実験

この問題の原因を探るため、必要最低限のデモページを作成しました。

マテリアルはライトやシェーダーの影響を受けないMeshBasicMaterialを使用しました。各レンダラーの色空間はデフォルトです。

実験結果

まず、RGBの値をすべて1に設定します。白を指定すると、RGB値はsRGB色空間とリニアsRGB色空間の影響を受けなくなります。

StudyColorSpaceAlpha1.jpeg

その上で、透明度を変更します。opacityを0.2程度に設定すると、WebGLRendererとWebGPURendererで異なる結果が得られます。

StudyColorSpaceAlpha2.jpeg

最後に、outputColorSpaceプロパティを変更します。リニアsRGBに設定すると、WebGLRendererの結果は変わりませんが、WebGPURendererの結果が変わります。

StudyColorSpaceAlpha3.jpeg

Three.jsにおけるカラーマネージメントの概要

デモページの実験結果を理解するために、Three.jsにおけるカラーマネージメントの仕組みを読み解いていきます。

  1. ソース色空間 : テクスチャやRGB入力値などの色空間で、ソースごとに異なる
  2. 作業色空間 : ColorManagement.workingColorSpaceに設定された色空間で、Three.jsのシェーダー内部で利用され、色情報の四則演算やライト計算などはこの色空間で行われる
  3. 出力色空間 : レンダラーがCanvasに描画する際の色空間で、outputColorSpaceプロパティで指定する

Three.jsはこの3つの色空間を相互変換しながら、レンダリングを行います。

それぞれの色空間のデフォルト値は以下の通りです。

  1. ソース色空間 : ソースによって異なる
  2. 作業色空間 : sRGB-linear
  3. 出力色空間 : sRGB

色変換を追う

それでは、色空間の変換を処理ごとに追っていきます。

Colorクラスの色指定関数には、カラースペースを引数として指定するものがあります。たとえば、setRGB()関数は、第四引数にソース色空間を指定できます。

setRGB関数の色空間引数は、ドキュメント上では固定の値として記載されていますが、ソースコード上ではColorManagementクラスのworkingColorSpaceプロパティを参照しています。

Colorクラスの色指定関数は、内部的にColorManagementクラスのtoWorkingColorSpace()関数を呼び出しています。この関数はソース色空間を作業色空間へ変換します。

return this.convert(color, sourceColorSpace, this._workingColorSpace);

setRGB()関数に色空間を指定しない場合、ソース色空間と作業色空間が同じなので変換は実行されません。

setHex関数やsetStyle関数はデフォルトのソース色空間がsRGBになっています。これはCSSとの互換性を考慮したためです。

Rendererによる色空間の変換

ColorManagement.workingColorSpaceプロパティは、レンダラー内部で使用される作業色空間を示しています。レンダラーはこの値で色の計算を行い、最後にレンダラーのoutputColorSpaceに変換してCanvasに描画します。

WebGPURendererでは、outputColorSpaceプロパティの変更でopacityのレンダリング結果が変わります。これは、作業色空間から出力色空間への変換が、透明度にも影響を与えていることを示します。

一方WebGLRendererでは、outputColorSpaceプロパティの変更でopacityのレンダリング結果が変わりません。opacityは色空間変換をバイバスします。

opacityを色変換する

WebGPURendererでWebGLRendererと同じようにMaterialの透明度を扱いたい場合は、Colorクラスの変換関数を利用しましょう。

const color = new Color();
color.setRGB(opacity, 0, 0, "srgb");
material.opacity = color.r;

Colorクラスを介して透明度を作業色空間に変換します。レンダラーはopacityを出力色空間に変換するため、WebGLRendererと同じ結果が得られます。

個人的な感想

透明度は色ではなく、本来は色空間に影響されないものです。そのため、opacityも色空間の変換に影響されないと思い込んでいました。WebGPURendererでは、Blenderなどの3Dツールとの連携も考慮して、このような変換が行われているのかもしれません。最小限のテストで挙動を確認することが大切です。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3