飴屋

WebGL/シェーダーマテリアル

そろそろそれっぽいことをしたくなってきました。前に「材質」を表すとだけ言うにとどめておいたマテリアルの話をしましょう。

  • LineBasicMaterial
  • LineDashedMaterial
  • MeshBasicMaterial
  • MeshDepthMaterial
  • MeshDistanceMaterial
  • MeshLambertMaterial
  • MeshMatcapMaterial
  • MeshNormalMaterial
  • MeshPhongMaterial
  • MeshPhysicalMaterial
  • MeshStandardMaterial
  • MeshToonMaterial
  • PointsMaterial
  • RawShaderMaterial
  • ShaderMaterial
  • ShadowMaterial
  • SpriteMaterial

今、Three.jsのドキュメントを確認したらこれだけの種類のマテリアルクラスが用意されてました。一つずつ開設はしませんが、ワイヤーフレームを描くだけのマテリアルもあれば、単色で塗りつぶすだけのマテリアル、形状のZ位置(奥行き位置)に応じて色が変わるマテリアル、法線方向によって色が変わるマテリアル・・・などなどいろいろですね。うまく使うと大概のことが描けてしまうのですごいですね。

それで今回やりたいのはShaderMaterialです。このマテリアルはシェーダーを指定して形状を描画できるようで、具体的には頂点シェーダーとフラグメントシェーダーを表す二つのスクリプトを渡すと、そのシェーダーを使って描画してくれるよってことのようです。シェーダーはモノをかたどるプログラムを指します。頂点シェーダーは簡単に言うと、ポリゴンの頂点位置(3D)をカンバス上の位置(2D)に変換する計算をする部分で、フラグメントシェーダーはポリゴンの三角形の中に1ピクセルずつ色を詰めていく作業を担当する部分ですね。

const geometry = new THREE.PlaneGeometry(width, height);
const material = new THREE.ShaderMaterial({
  vertexShader: vShader,
  fragmentShader: fShader,
  uniforms: uniforms
});
const mesh = new THREE.Mesh(geometry, material);

ShaderMaterialにvertexShader、fragmentShader、uniformsを渡しました。uniformsって何でしょうね?

const vShader = `
void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;

vertexShaderはよく「お決まり」と↑こんな風に書かれています。これがGLSLってやつですか。JavaScriptでないスクリプトであることはすぐわかると思います。そして宣言されてもいない変数っぽいものが唐突に現れます。大事なことはgl_Positionにカンバス上の座標が計算されて入るってことのようです。変数名から想像するに

projectionMatrix
透視変換行列
modelViewMatrix
物体のローカル座標をワールド座標に変換して、さらにカメラの視点からの座標に変換する行列
position
計算対象の頂点座標(3D)

こんな感じでしょう。本来であればこういう変数を自分でちゃんと定義しなくちゃならないはずですが、Three.jsが代理でやってくれているってことのようです。偉い、Three.js!GPUで計算させる都合上、データ型は厳密である必要があります。行列の積を表現するのにXYZの三値だと4x4行列と計算できないのでvec4( position, 1.0 ) と一つ数字を足して四値のベクトルデータにしたりしてますね。

const fShader = `
void main(void)
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

fragmentShaderはgl_FragColorにピクセルの色を詰め込むのが大事なことです。とりあえず、全部赤にしときます。RGBの数字を指定しているだけです。

const uniforms = {
  xyvec: { type: "v2", value: new THREE.Vector2() }
};

uniformsはシェーダー間で使える変数みたいなものを定義する仕組みです。今回は使ってません。何かしらの計算に使いたい数値って表現したいものよっていろいろあるので、ここに格納するんでしょうね。

説明することが多くて面白い出力まで辿り着けなかったな・・・。

Last-Modified