のぐそんブログ

暗いおじさんがシコシコ書くブログです。

WebGLでの行列による変換処理を理解する上で、最低限知る必要がある言葉

WebGLでの行列による変換処理を理解する上で、最低限しっていないといけない言葉について書きたいと思います。

下記を参考にさせていただきました。 3D 描画の基礎知識

OpenGLの座標系

OpenGL右手座標系 です。 X座標は右に行くほど、大きくなります。 Y座標は上に行くほど、大きくなります。 Z座標は手前にくるほど、大きくなります。

モデル座標変換行列(ワールド変換行列)

3次元空間での頂点の位置の操作で使用します。 頂点の平行移動や、回転、拡大縮小などがモデル座標変換行列で行えます。

3次元空間の原点から見て、対象となるモデル(オブジェクト)がどの座標にあるかを変換します。

ビュー座標変換行列

ビュー座標変換は、その名の示すとおりビューつまりカメラの役割です。 3次元空間内で、描画を開始する位置や、向き、視野角などをビュー座標変換を使って定義します。

プロジェクション座標変換行列

プロジェクション座標変換行列は、いわゆるプロジェクターのように「投影」に関する変換を行う座標変換です。3次元空間内の描画領域を定義します。

実際はスクリーン(平面)に投影する為、近いオブジェクトは大きく、遠いオブジェクトは小さくなどの2Dでの表示への変換が行われる。

MVPマトリックス

最終的にシェーダーに送る行列は、モデル、ビュー、プロジェクションをかけ合わせたものになります。

まとめ

描画に至るまでに、多くの座標変換処理を行っているようです。 難しい。。。

Three.jsでパーティクルを作ろうと思った際に調べたこと

Three.jsでパーティクルをつくるにはどうすればいいのか調べてみました。

THREE.Spriteでパーティクル

THREE.SpriteオブジェクトはTHREE.Object3Dオブジェクトを継承しており、THREE.Meshと同じように動作します。

Spriteは、何もプロパティをあたえないと、常に面をカメラの方に向けている2Dの平面です。

 let material = new THREE.SpriteMaterial();
    let sprite = new THREE.Sprite(material);
    scene.add(sprite);

See the Pen YQNZqg by nogson (@satofaction) on CodePen.

THREE.Spriteに渡せるマテリアルは、THREE.SpriteMaterialか、THREE.SpriteCanvasMaterialのいずれかです。

パーティクルを作成する際に、Spriteを大量に作成してもそれっぽいのができそう。 ただし、オブジェクト大量に作成するとパフォーマンス的によくありません。

See the Pen LLxWBv by nogson (@satofaction) on CodePen.

THREE.Points

THREE.Pointsは大量の頂点データを管理するのに便利です。 頂点座標と塗のデータをジオメトリに追加します。 パーティクルのサイズはマテリアルのプロパティで調整します。 頂点カラーを変更するためにはvertexColorsとtrueに設定します。

 let geometry = new THREE.Geometry();
 let material = new THREE.PointsMaterial({
     //pointsを使用する場合はMaterialのサイズで調整する
     size:0.1,
     vertexColors:true
 });

 let range = 1000;

 for (let i = 0; i < range; i++) {

      let pos = getPostion(
          Math.random() * width,
          Math.random() * height,
          Math.random() * width
      );

      //頂点データを生成
      let particle = new THREE.Vector3(pos.x,pos.y,pos.z);

      //頂点色を設定
      let color = new THREE.Color(0xffff);
                
      //頂点データをジオメトリに追加
      geometry.vertices.push(particle);

      //頂点色をジオメトリに追加
      geometry.colors.push(color);

 }

point = new THREE.Points(geometry,material);
scene.add(point);

See the Pen owBZKv by nogson (@satofaction) on CodePen.

THREE.PointsMaterialのプロパティ

プロパティ 説明
color Points内のすべてのパーティクルの色を一括指定できる。vertexColorsプロパティをtrueにして、ジオメトリに頂点カラーを設定した場合は、ジオメトリの頂点カラーが有効になる。| |map|マップを使うとパーティクルにテクスチャを設定できる
size パーティクルのサイズ
sizeAttenuation falseを設定すると、カメラからの距離にかかわらずパーティクルが同じ大きさになる
vertexColors パーティクルの頂点カラーの設定を有効にする
opacity 透明度を設定
transparent trueを設定すると、opacityプロパティが有効になる
blendind パーティクルのブレンドモードを設定
fog パーティクルがシーンのfogの影響を受けるかを設定。デフォルトはtrue
depthTes パーティクルがシーンのfogの影響を受けるかを設定。デフォルトはtrue

パーティクルにテクスチャを貼ってみる

画像を読み込んでmapプロパティに下のテクスチャを貼ってみます。

loader = new THREE.TextureLoader();
loader.load('images/img.png', function (texture) {
    createPoints(texture);
    render();
});


function createPoints(texture) {
    let geometry = new THREE.Geometry();
    let material = new THREE.PointsMaterial({
        //pointsを使用する場合はMaterialのサイズで調整する
        size: 0.2,
        color: 0xffffff,
        vertexColors: true,
        map: texture,
        transparent: true,
    });

    let maxLength = 2000;

    for (let i = 0; i < maxLength; i++) {

        let pos = getPostion(
            Math.random() * width,
            Math.random() * height,
            Math.random() * width
        );

        //頂点データを生成
        let particle = new THREE.Vector3(pos.x, pos.y, pos.z);

        //頂点色を設定
        let color = new THREE.Color(0xffffff);

        //頂点データをジオメトリに追加
        geometry.vertices.push(particle);


        //頂点色をジオメトリに追加
        geometry.colors.push(color);

    }

    point = new THREE.Points(geometry, material);
    scene.add(point);
}

こんな感じになりました。

Kobito.65GIWm.png

しかしいくつか問題がありました。 頂点の描画順で重なり順が決まる為、パーティクルが重なった場合に深度テストが影響して、画像の透明部分がうまく描画できませんでした。

震度テストを無効(depthTest: false )にしましたが、今度はサイズの小さいパーティクルがサイズの大きなオブジェクトより前に出てしまいました。

かと言って、z座標をいじるとそもそもの動きがおかしくなってしまいました。

まとめ

1万頂点ぐらいまでなら、PCが唸らずに描画できました。 どうも10万頂点以上いくと、パーフォーマンスなどに影響があるので気をつけたほうが良いようです。

実際今回つくったサンプルはこちらです。

Three.jsで頂点座標を指定して三角形を描く

以前、「WebGLを使って三角形を描画する為の基礎知識」の記事をかきましたが、WebGLのラッパーライブラリであるTHREE.jsでも同じようなことができるのでメモしておきます。

当然ですが、ナマのWebGLを触るよりより簡単に書けるようになっています。

続きを読む

expressでサーバ−を立てるの超基礎編

サーバー側の知識が限りなくゼロに近いオジサンですが、 expressを使って、まずはindex.htmlを表示だけしてみようと思います。

続きを読む

Socket.ioの超基礎編

expressとSocket.ioを使う

サーバー側の知識が限りなく0に近いオジサンですが、 Socket.ioを使って、サーバーとクライアントで双方向通信をやってみます。

続きを読む

THREE.Sceneについて少し調べる

THREE.Sceneは、オブジェクトを配置する基盤なのですが、THREE.Scene.addしか使ったことがなかったので、他にどんなことができるか調べました。

続きを読む

WebGLを使って三角形を描画する為の基礎知識

WebGLを使って三角形を描画する為の基礎知識を学びたいと思います。 ちなみに、こちらに記載されている内容だけでは三角形は描画できません。

続きを読む