OpenGLを使用してテクスチャを描画する|Android開発

androidOpenGLを使ってテクスチャを貼り付け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()で行っている処理になります。

  1. glGenTextures()でテクスチャオブジェクトを生成し、glBindTexture()でバインドします
  2. texImage2D()でテクスチャ用の画像を設定します

今回はテクスチャ用の画像を2枚用意し、リソースファイルとして登録しました。

リソース名 画像
R.drawable.front gl-texture-front
R.drawable.rear gl-texture-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軸180度

Y軸方向に315度回転した描画

テクスチャ描画Y軸315度

GL10.GL_DEPTH_TESTの効果

TestGLView.LocalRendererクラスのonSurfaceCreated()gl.glEnable(GL10.GL_DEPTH_TEST)をコールしない場合は、正面から見た時に以下のようになります。

GL_DEPTH_TESTなし

正面の画像が見えずに、後から描画した後面が見えている状態になっています。

3Dオブジェクトを回転させる方法

描画を行う前に、gl.glRotatef()をコールします。

引数 内容
angle 回転角
x X軸の回転かどうか(1 または 0)
y Y軸の回転かどうか(1 または 0)
z Z軸の回転かどうか(1 または 0)

軸と回転方向

正面から見た軸と回転方向の関係を表した図です。座標は矢印の方向に増加します。

OpenGL回転軸
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です