OpenGL ESでテクスチャ

http://d.hatena.ne.jp/kambayashi/20090711/1247591143のサンプルを使用。
http://d.hatena.ne.jp/kambayashi/20090714/1247677550までの変更を加えたバージョン。

テクスチャ(画像)を用意する

画像は縦横が2のn乗のサイズにする(64x64、128x128、256x256など)。
小さすぎると読めないが32x32以上くらいにしておけば安心。
今回使用するテクスチャはこれ。サイズは64x64。
f:id:kambayashi:20090716002954p:image

テクスチャをプロジェクトに入れる

(プロジェクトディレクトリ)/res/drawableにコピーする。
f:id:kambayashi:20090716003657j:image
上記のディレクトリに入れた後、eclipse上でプロジェクトを右クリックしてメニューを開き、リフレッシュを選択する。

テクスチャ用の機能設定を行う

http://d.hatena.ne.jp/kambayashi/20090714/1247677550で作ったglInitialize()の
gl.glEnable(GL10.GL_TEXTURE_2D)のコメントアウトを解除する。

テクスチャ読み込み

プログラム中でテクスチャを読み込み、OpenGL ESで使えるように準備する。
今回はプログラム開始時(OpenGL ESの準備完了時)に読み込むので、GLRendererのonSurfaceCreated()で行う。
そのための準備として、GLRendererにActivityを渡しておく。
f:id:kambayashi:20090716004438j:image

それが出来たら、onSurfaceCreated()に以下の処理を追加する。

//リソース読み込み
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.android_icon);
//テクスチャ管理番号割り当て。複数枚読み込むときは1の部分の数値を増やす。
int[] textureNo = new int[1];
gl.glGenTextures(1, textureNo, 0);
//テクスチャ管理番号バインド
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureNo[0]);
//GL用のメモリ領域に画像データを渡す。上でバインドされたテクスチャ管理番号と結び付けられる。
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

//プロパティに設定
mTextureNo = textureNo[0];

いつのまにかmTextureNoというプロパティが作られているが、これもGLRendererに入れておく。

描画

描画に使ってきたGLHelperクラスをテクスチャを貼り付けるために作り変える。
修正が多いので、GLHelperクラス全文掲載。GLHelper.draw()にテクスチャ番号も渡すようになる。

/**
 * 描画補助クラス
 */
class GLHelper{
	//頂点バッファ
	private FloatBuffer buffer;
	//テクスチャ座標バッファ
	private FloatBuffer textureBuffer;
	
	/**
	 * コンストラクタ
	 */
	public GLHelper(){
		{
			//頂点数x頂点構成要素数x4バイトのサイズのバッファ作成
			ByteBuffer vb = ByteBuffer.allocateDirect(4 * 3 * 4);
			vb.order(ByteOrder.nativeOrder());	//ビッグエンディアンかリトルエンディアンにあわせてくれる
			buffer = vb.asFloatBuffer();
	
			//頂点データで頂点バッファ作成
			float[] vertices = {
					// X,Y,Zの3要素で四角形を構成する4頂点
					-0.5f, -0.5f, 0.0f,		//座標(0,0,0)を中心に左下
					0.5f, -0.5f, 0.0f,		//		〃			右下
					-0.5f, 0.5f, 0.0f,		//		〃			左上
					0.5f, 0.5f, 0.0f,		//		〃			右上
			};
			buffer.put(vertices);
			buffer.position(0);
		}
		
		{
			//頂点数x頂点構成要素数x4バイトのサイズのバッファ作成
			ByteBuffer vb = ByteBuffer.allocateDirect(4 * 2 * 4);
			vb.order(ByteOrder.nativeOrder());	//ビッグエンディアンかリトルエンディアンにあわせてくれる
			textureBuffer = vb.asFloatBuffer();
	
			//頂点データで頂点バッファ作成
			float[] vertices = {
					// 画像データの左上を原点に、0.0~1.0の範囲の座標
					0.0f, 1.0f,		//左下
					1.0f, 1.0f,		//右下
					0.0f, 0.0f,		//左上
					1.0f, 0.0f,		//右上
			};
			textureBuffer.put(vertices);
			textureBuffer.position(0);
		}
	}
	
	/**
	 * 描画
	 * @param gl	GL操作ハンドル
	 */
	public void draw( GL10 gl, int textureNo ){
		//ポリゴンカラー設定
		gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		//テクスチャ管理番号バインド
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureNo);
		//頂点バッファ機能ON
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		//頂点バッファ設定
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, buffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
		//描画
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
	}
}

以上の修正を加えて実行すると以下のような画面になる。
f:id:kambayashi:20090716024916j:image