GLSurfaceViewを使ったOpenGL ES1.0の初期化が出来たので、続いてGLSurfaceViewに三角形を描いてみましょう。

OpenGL ES 1.0では、頂点のデータを設定した後OpenGLの図形を描く描画コマンドを実行すると、画面上に図形が描画されます。デフォルトの座標系では、描画領域全体を(-1.0, -1.0)~(1.0, 1.0)に対応させるXY平面上にZ軸が配置されているので、この範囲に入るよう頂点を置いて図形を描けば、画面上に表示されるわけです(Z座標は、カメラやデプスを設定しないと意味を持ちません)。

今回は、三角形を描くために(-0.5, -0.5, 0)(0, 0.5, 0)(0.5, 0.5, 0)というfloat型数値による三つの頂点を用意し、AndroidのOpenGL ESシステムに渡すことにします。

Androidアプリを動かすJava仮想マシンからOpenGL ESにデータを渡すには、Bufferオブジェクトの形にする必要があるので、まず頂点のデータをfloat型配列にしてからFloatBufferを作成します。

// 頂点をfloat配列に格納
float[] vlist = new float[]{-0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f};

// 頂点データ格納用ByteBufferを作成
ByteBuffer bbuf = ByteBuffer.allocateDirect(vlist.length * 4);

// バイトオーダー設定
bbuf.order(ByteOrder.nativeOrder());

// ByteBufferからFloatBufferを作成
mVlist = bbuf.asFloatBuffer();

// 配列をバッファに転送
mVlist.put(vlist);

// 現在位置をバッファ先頭に設定
mVlist.position(0);

これで頂点を格納したバッファが用意できました。あとは頂点を設定できるようにglEnableClientState()で頂点配列を有効化すれば、準備完了です。

実際の描画時には、全体をクリアした後glVertexPointer()でOpenGL ESに頂点データを設定します。続いて、glDrawArrays()も図形の種類(今回は三角形を示すGL10.GL_TRIANGLES)、頂点データのオフセットと頂点の数を指定し(今回は最初から三つの頂点を使うので、0と3を指定)を渡すと画面上に描画されます。

今回は、描画時の色を指定するglColor4f()で背景の補色となる色を設定してみました。

import java.nio.*;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity implements Renderer {

    private GLSurfaceView mGLView;
    private float mBGD, mBGDD;

    FloatBuffer mVlist;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mBGD = 0;
        mBGDD = 0;

        mGLView = new GLSurfaceView(this);

        mGLView.setRenderer(this);

        setContentView(mGLView);

    }

    @Override
    protected void onPause() {

        super.onPause();
        mGLView.onPause();

    }

    @Override
    protected void onResume() {

        super.onResume();
        mGLView.onResume();

    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        // 頂点をfloat配列に格納
        float[] vlist = new float[]{-0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f};

        // 頂点データ格納用ByteBufferを作成
        ByteBuffer bbuf = ByteBuffer.allocateDirect(vlist.length * 4);

        // バイトオーダー設定
        bbuf.order(ByteOrder.nativeOrder());

        // ByteBufferからFloatBufferを作成
        mVlist = bbuf.asFloatBuffer();

        // 配列をバッファに転送
        mVlist.put(vlist);

        // 現在位置をバッファ先頭に設定
        mVlist.position(0);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

        gl.glViewport(0, 0, width, height);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    }

    @Override
    public void onDrawFrame(GL10 gl) {

        gl.glClearColor(mBGD, mBGD * mBGD, 1.0f - mBGD, 1.0f);

        mBGD += mBGDD;

        if (mBGD >= 1.0f) {
            mBGDD = -0.01f;
        }

        if (mBGD <= 0) {
            mBGDD = 0.01f;
        }

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        gl.glColor4f(1.0f - mBGD, 1.0f - (mBGD * mBGD), mBGD, 1.0f);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVlist);
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

    }

}

このソースをAndroidアプリとしてビルドし起動すると、画面全体が塗りつぶされ中央に三角形が描かれます。


創作プログラミングの街