SSブログ

Androidアプリ開発 OpenGL ポイントスプライト [Android OpenGL]

本日は「ポイントスプライト」をやってみる。AREarthroidでは使用していないテクニックだが、うまくいけば組み込むかも知れない。



ポイントは「点」という意味。ポリゴンは面なので、頂点がいくつか集まって構成されている。OpenGL ESでは、三角形しか扱えないので、ポリゴンの頂点数は3となる。
OpenGLでは、面しか描けないかというとそうでもなく、GL_LINESなら線を描けるし、GL_POINTSなら点を描画することができる。OpenGL ESにも点、線の描画機能がある。

スプライトっていうのは、ゲーム用語なのかな。2Dゲーム中のキャラクタを、高速に表示させるためのしくみのことを言っていたと記憶している。

で、3DCGのポイントスプライトになると、表示する位置は、点で決めてやって、そこにいつもこちら向きにないように仮想的な面を作って、テクスチャマッピングして表示する。っていうことらしい。

パーティクルを使った粒子シミュレーションでは、多くの点を描画しないといけない。量が多くなれば、それだけ精密に見える。面より点の方がデータ量が少ないので、大量のパーティクルを作りたいときは点の方が有利。

うんちくはこれくらいにして、まずは、点を描画してみよう。

まじめにデータを作成していると日が暮れるので、乱数で生成することにした。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Points {
	private FloatBuffer buffer;			// 頂点用バッファ
	private final int numOfPoints = 1000;

	public Points() {
		ByteBuffer vb = ByteBuffer.allocateDirect(numOfPoints * 3 * 4);
		vb.order(ByteOrder.nativeOrder());
		buffer = vb.asFloatBuffer();
		float x, y, z;
		for ( int i = 0; i < numOfPoints; i++ ){
			x = (float)(Math.random() * 8.0 - 4.0);
			y = (float)(Math.random() * 8.0 - 4.0);
			z = (float)(Math.random() * 8.0 - 6.0);
			buffer.put(x);
			buffer.put(y);
			buffer.put(z);
		}
		buffer.position(0);
	}

	public void draw(GL10 gl) {
		gl.glPushMatrix();		// マトリックス記憶
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, buffer);
		gl.glDrawArrays(GL10.GL_POINTS, 0, numOfPoints);
		gl.glPopMatrix();		// マトリックスを戻す
	}

}


クラスを追加した。ソースファイルはPoints.javaである。
何をやっているかというと、1000個の点をランダムな位置に生成して描画いる。っていうだけ。

これをレンダラーで描画する。

public class SampleGLSurfaceView extends GLSurfaceView implements OnGestureListener {
	private ArrayList models = new ArrayList();
	private Points points = new Points();
	private float eyepos[] = new float[3];


Pointsのインスタンスは、フィールドpointsで作成。
onDrawFrameで、ドロイド君を描画する前でpointsのdrawを呼び出して描画っと。

		@Override
		public void onDrawFrame(GL10 gl) {
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

			// ライティングをON
			gl.glEnable(GL10.GL_LIGHTING);
			// 光源を有効にして位置を設定
			gl.glEnable(GL10.GL_LIGHT0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightpos, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, white, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, white, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, yellow, 0);

			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();

			// カメラ位置を設定
			GLU.gluLookAt(gl, eyepos[0], eyepos[1], eyepos[2], 0, 0, 0, 0, 1, 0);

			gl.glEnable(GL10.GL_BLEND);
			gl.glEnable(GL10.GL_TEXTURE_2D);
			// スムースシェーディング
			gl.glShadeModel(GL10.GL_SMOOTH);
			// フォグ
			gl.glEnable(GL10.GL_FOG);
			gl.glFogfv(GL10.GL_FOG_COLOR, black, 0);
			gl.glFogx(GL10.GL_FOG_MODE, GL10.GL_LINEAR);
			gl.glFogf(GL10.GL_FOG_START, 3.0f);
			gl.glFogf(GL10.GL_FOG_END, 10.0f);

			// ポイントスプライトを表示
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, white, 0);
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, white, 0);
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, white, 0);
			gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
			gl.glDisable(GL10.GL_TEXTURE_2D);
			gl.glDisable(GL10.GL_BLEND);
			points.draw(gl);

			// ソート
			Collections.sort(models, new ModelComparator());

			for ( Model m : models ){
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, gray, 0);
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, gray, 0);
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, gray, 0);
				gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
				gl.glEnable(GL10.GL_TEXTURE_2D);
				gl.glEnable(GL10.GL_BLEND);
				gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
				m.draw(gl);

				// 2回目の表示はハイライトを出すため
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, transparent, 0);
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, half_white, 0);
				gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, half_white, 0);
				gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
				gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
				m.draw(gl);
				
				m.rotate();
			}
		}




おお、フォグも効いているので、宇宙空間的な感じになったではないか。
これは、AREarthroidにも組み込まないといけないか。

ここまでで、点を描画できたので、拡張して、テクスチャを貼ってやれば、ポイントスプライトの完成となる。

		@Override
		public void onDrawFrame(GL10 gl) {
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

			// ライティングをON
			gl.glEnable(GL10.GL_LIGHTING);
			// 光源を有効にして位置を設定
			gl.glEnable(GL10.GL_LIGHT0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightpos, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, white, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, white, 0);
			gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, yellow, 0);

			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();

			// カメラ位置を設定
			GLU.gluLookAt(gl, eyepos[0], eyepos[1], eyepos[2], 0, 0, 0, 0, 1, 0);

			gl.glEnable(GL10.GL_BLEND);
			gl.glEnable(GL10.GL_TEXTURE_2D);
			// スムースシェーディング
			gl.glShadeModel(GL10.GL_SMOOTH);
			// フォグ
			gl.glEnable(GL10.GL_FOG);
			gl.glFogfv(GL10.GL_FOG_COLOR, black, 0);
			gl.glFogx(GL10.GL_FOG_MODE, GL10.GL_LINEAR);
			gl.glFogf(GL10.GL_FOG_START, 3.0f);
			gl.glFogf(GL10.GL_FOG_END, 10.0f);

			// ポイントスプライトを表示
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, white, 0);
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, white, 0);
			gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, white, 0);
			gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
			gl.glEnable(GL10.GL_TEXTURE_2D);
			gl.glEnable(GL10.GL_BLEND);
			gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
			//ポイントスプライト
			gl.glEnable(GL11.GL_POINT_SPRITE_OES);
			gl.glActiveTexture(GL10.GL_TEXTURE0);
			gl.glTexEnvf(GL11.GL_POINT_SPRITE_OES, GL11.GL_COORD_REPLACE_OES, GL10.GL_TRUE);
			gl.glPointSize(32.0f);
			points.draw(gl);





わわ、ドロイド君がいっぱい。




サイト内を検索

nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。



Copyright Atsushi Asai Google+朝井淳
[改訂第4版]SQLポケットリファレンス

[改訂第4版]SQLポケットリファレンス

  • 作者: 朝井 淳
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/02/18
  • メディア: 単行本(ソフトカバー)

イラストで理解 SQL はじめて入門

イラストで理解 SQL はじめて入門

  • 作者: 朝井 淳
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/05/16
  • メディア: 単行本(ソフトカバー)

[データベースの気持ちがわかる]SQLはじめの一歩 (WEB+DB PRESS plus)

[データベースの気持ちがわかる]SQLはじめの一歩 (WEB+DB PRESS plus)

  • 作者: 朝井 淳
  • 出版社/メーカー: 技術評論社
  • 発売日: 2015/03/03
  • メディア: 単行本(ソフトカバー)

Access クエリ 徹底活用ガイド ~仕事の現場で即使える

Access クエリ 徹底活用ガイド ~仕事の現場で即使える

  • 作者: 朝井 淳
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/05/25
  • メディア: 大型本

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。