three.jsで頂点カラーを設定する
方法を忘れそうなのでメモ書きとして。
前提
- threejsバージョン: r139
- GPU: NVIDIA GeForce
※three.jsはよく仕様変更されるので後々通用しなくなる可能性あり
本文
とりあえずサンプルコード、頂点カラーを設定したシンプルな平面Meshを生成します。
コード全体はこちら:実行サンプルコード
// ヘルパー
function getVertexNum(geometry: BufferGeometry) {
const posAttr = geometry.getAttribute("position");
return posAttr.array.length / posAttr.itemSize;
}
// コンフィグ変数
const useAlphaChannel: boolean = false;
const colorList = [
new Color(0x990000),
new Color(0x009900),
new Color(0x000099),
new Color(0xffffff)
];
// Geometry: attribute "color"を設定
const geometry = new PlaneGeometry(SCREEN_WIDTH * 0.8, SCREEN_HEIGHT * 0.8);
{
const colorItemSize = useAlphaChannel ? 4 : 3;
const vertexColorData = [];
let colorListIndex = 0;
for (
let i = 0, len = getVertexNum(geometry) * colorItemSize;
i < len;
i += colorItemSize
) {
const color = colorList[colorListIndex];
vertexColorData[i] = color.r;
vertexColorData[i + 1] = color.g;
vertexColorData[i + 2] = color.b;
if (useAlphaChannel) vertexColorData[i + 3] = i / len;
// colorListループ
if (colorList.length <= ++colorListIndex) colorListIndex = 0;
}
geometry.setAttribute(
"color",
new Float32BufferAttribute(vertexColorData, colorItemSize)
);
}
// Material: vertexColorsオプションをtrue
const material = new MeshBasicMaterial({
vertexColors: true,
transparent: useAlphaChannel
});
// Create Mesh
const mesh = new Mesh(geometry, material);
mesh.position.set(SCREEN_WIDTH * 0.5, SCREEN_HEIGHT * 0.5, 0);
scene.add(mesh);
コードが若干長くなって読みづらいですが、大事なポイントとしては
- Geometry側:geometry.setAttributeで”color”をセットする
- Material側:material.vertexColorsオプションをtrueにする
ということだけです。
色値はR・G・B値を各頂点ごとに設定する形ですが、一般的な0 ~ 255
ではなく、0 ~ 1.0
で設定することに注意です(値がオーバーしても動作上は問題ないですが)。
上記コードのようにTHREE.Colorクラスを使うと楽です。
アルファ値(透明度)の設定
またアルファ値の設定も可能です。これはsetAttributeの際にitemSizeを4にすることで自動的にthree.js側がよろしく設定してくれます。(もちろん実データ側の更新を忘れずに)
- ただしmaterial側の
transparent
パラメータをtrueにしないと反映されないことに注意。 - ちなみに以前は
vertexAlphas
というオプションがあったようで、検索ではこちらを使った方法が出てきますが、現版には存在しないので注意(内部パラメータとしては存在)
サンプルコードではuseAlphaChannel
変数フラグの切り替えで反映させてます(値はテキトーです)
おまけ:ShaderMaterialでのcolor変数の扱い
ShaderMaterialで独自のvertexシェーダーを定義するとき、vertexColorsをtrueにしているときは宣言なくcolor変数が使えます。
varying vec3 vColor;
void main() {
vColor = color; // <- ここ
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
}
これは組み込みのattributeとしてthree.jsプログラムオブジェクトが自動的に宣言を付与してくれているためです。(上記コードでいうprojectionMatrix
などと同様)
なおデフォルト設定ではvertexColors
はfalseのため、宣言が省かれます。その場合コンパイルエラーになることに注意。