Point Spriteによる2Dスプライト・エンジンについて

公開:2017-11-15 21:18
更新:2020-02-15 04:37
カテゴリ:シューティングゲーム,ゲーム製作,HTML5,ES6,JS,Blender

Blenderでモデリングしている合間に、three.jsのShader MaterialとPoint Spriteを使って、2Dスプライト・エンジンを作ってみた。 動機としては、以前作った2Dスプライト・エンジンは、処理的に無駄が多いので。

ポイントスプライトというのは、「1点で正方形を描くGPUの機能」と言える。1つの点の位置とサイズを指定すると、正方形が描画できるのである。 ただWebGLでは、描ける点のサイズに制限がある(大体は64px * 64pxくらいまで)。

今までは四角形1つ描くのに4つの頂点を使っていたから、2Dスプライトエンジンの効率化にはうってつけではないか。しかも私の場合、低解像度志向なので64pxもあれば十分な大きさである。それよりも大きいものは今まで通り4つの頂点を使えばいい。

ただし、ポイントスプライトを使うと正方形しか描けず、また1点なので回転などの表現ができない。これを実現するには角度というAttributeを用意して、シェーダーでテクスチャ・サンプルするときに読み出し位置を回転させればよい。

ということで書いたシェーダーは以下のとおり。Three.jsのシェーダー・マテリアルで使うことを前提としている。 コードではさらにスプライトNOを指定すれば、指定した番号のビットマップ・セルを表示するようにしてみている。


const vertexShader = `

attribute vec3 pointColor;
attribute float size;
attribute float visible;
attribute float spriteNo;
attribute float rotate;

varying vec3 vColor;
varying float vVisible;
varying float vSpriteNo;
varying float vRotate;

void main() {

  vColor = pointColor;
  vVisible = visible;
  vSpriteNo = spriteNo;
  vRotate = rotate;

  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

  gl_PointSize = size;

  gl_Position = projectionMatrix * mvPosition;

}
`;

const fragmentShader = `
uniform vec3 color;
uniform float spriteSize;
uniform sampler2D texture;

varying vec3 vColor;
varying float vVisible;
varying float vSpriteNo;
varying float vRotate;

void main() {

  if(vVisible == 0.0) discard;

  //gl_FragColor = vec4( color * vColor, 1.0 );
  //gl_FragColor = /*gl_FragColor */ texture2D( texture, gl_PointCoord / 4.0 );
  vec2 coord = gl_PointCoord - 0.5;
  vec2 coord2;
  float s = sin(vRotate);
  float c = cos(vRotate);
  coord2.x = coord.x * c - coord.y * s;
  coord2.y = coord.x * s + coord.y * c;
  coord = coord2 + 0.5;
  if(coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0 ) discard;

  coord.x = coord.x / 16.0 + vSpriteNo / 16.0;
  coord.y = coord.y  / 16.0 + 14.0 / 16.0;
  gl_FragColor = texture2D( texture, coord);//vec4(1.0,1.0,1.0,1.0);
}
`;

動作サンプル

新しいウィンドウで開く

ソースコード・リソース

/dev/shooting3/devver/20171116/css/style.css

/dev/shooting3/devver/20171116/index.html

/dev/shooting3/devver/20171116/js/bundle.js

/dev/shooting3/devver/20171116/js/dsp.js