OpenGLを使用してテクスチャを描画する|Android開発
android
でOpenGL
を使ってテクスチャを貼り付け3Dモデルを描画をする方法です。ビューやアクティビティの設定は下記記事と同じで描画処理の変更とテクスチャの初期化が追加になります。
OpenGLを使用して図形を描画をする|Android開発
Renderer の変更
TestGLView.LocalRenderer
クラスのonSurfaceCreated()
でテクスチャの初期化処理を行います。
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// デプステストを設定. 隠れている面を表示しない. 後から書いた三角形で上書きしない.
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
// テクスチャの初期化処理.
mDrawObject.init(gl, TestGLView.this.getContext());
}
描画モデルの実装
テクスチャ描画用のクラスDrawTextureObject
を作成します。
テクスチャの初期化
下記ソースコードのinit()
で行っている処理になります。
glGenTextures()
でテクスチャオブジェクトを生成し、glBindTexture()
でバインドしますtexImage2D()
でテクスチャ用の画像を設定します
今回はテクスチャ用の画像を2枚用意し、リソースファイルとして登録しました。
リソース名 | 画像 |
---|---|
R.drawable.front | |
R.drawable.rear |
座標情報の定義
テクスチャを描画するための頂点座標と対応するテクスチャの座標を定義します。下記ソースコードのコンストラクタで定義・実装している処理になります。
- 頂点座標は左下・右下・右上・左上の順で記述します
値の範囲は-1.0~1.0です
- テクスチャの座標は左上・右上・右下・左下の順で記述します
値の範囲は0.0~1.0です
テクスチャの描画
glBindTexture()
でテクスチャIDを指定し、glDrawArrays()
で描画座標を指定します。
サンプルコード
public class DrawTextureObject {
public final FloatBuffer mmVertexBuffer;
public final FloatBuffer mmTextureBuffer;
private static int[] mmTextureIds = new int[] {
R.drawable.front,
R.drawable.rear,
};
private int[] mTextures;
public DrawTextureObject() {
// 左下、右下、右上、左上の順にする.
float vertices[] = {
// 正面.
-0.5f, -0.5f, 0.8f,
0.5f, -0.5f, 0.8f,
0.5f, 0.5f, 0.8f,
-0.5f, 0.5f, 0.8f,
// 後面.
0.5f, -0.5f, -0.8f,
-0.5f, -0.5f, -0.8f,
-0.5f, 0.5f, -0.8f,
0.5f, 0.5f, -0.8f,
};
// 左上、右上、右下、左下の順.
float texture[] = {
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
mmVertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mmVertexBuffer.put(vertices);
mmVertexBuffer.position(0);
mmTextureBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mmTextureBuffer.put(texture);
mmTextureBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D);
// 頂点データでの描画をするよ.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mmVertexBuffer);
// テクスチャ座標の配列を有効にするよ.
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mmTextureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 4, 4);
}
public void init(GL10 gl, Context context) {
mTextures = new int[mmTextureIds.length];
gl.glGenTextures(mmTextureIds.length, mTextures, 0);
gl.glActiveTexture(GL10.GL_TEXTURE0);
Bitmap bmp;
for (int i = 0; i < mmTextureIds.length; i++) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[i]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
bmp = BitmapFactory.decodeResource(context.getResources(), mmTextureIds[i]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
}
}
}
正面から見た描画
Y軸方向に180度回転した描画
Y軸方向に315度回転した描画
GL10.GL_DEPTH_TESTの効果
TestGLView.LocalRenderer
クラスのonSurfaceCreated()
でgl.glEnable(GL10.GL_DEPTH_TEST)
をコールしない場合は、正面から見た時に以下のようになります。
正面の画像が見えずに、後から描画した後面が見えている状態になっています。
3Dオブジェクトを回転させる方法
描画を行う前に、gl.glRotatef()
をコールします。
引数 | 内容 |
---|---|
angle | 回転角 |
x | X軸の回転かどうか(1 または 0) |
y | Y軸の回転かどうか(1 または 0) |
z | Z軸の回転かどうか(1 または 0) |
軸と回転方向
正面から見た軸と回転方向の関係を表した図です。座標は矢印の方向に増加します。