【Kotlin×Android】OpenGLを使う方法


グラフィック描画ライブラリーであるOpenGLはAndroidアプリ開発でも利用することができます。

今回はその利用方法をまとめたいと思います。


AndroidのViewはxmlを記述するか、GUIでパーツを追加することで編集することができます

今回はプログラムからViewを作成します。

MainActivityを修正します。

package com.example.glsample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.opengl.GLSurfaceView

class MainActivity : AppCompatActivity() {
    private  lateinit  var glView: GLSurfaceView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        glView = GLSurfaceView(this)
        glView.setRenderer(GLRender())
        setContentView(glView)

    }

    override fun onPause() {
        super.onPause()
        glView?.onPause()
    }

    override fun onResume() {
        super.onResume()
        glView?.onResume()
    }
}


onPauseやonResumeが実行されたとき使用したメモリに対して必要な処理を実行するため GLSurfaceViewのonPauseとonResumeを呼び出しています。
これはまじないみたいなものですかね。

さらにここではViewから GLSurfaceView のオブジェクトを取得し、そこにRenderを設定しています。

ここでいう Render とはGLSurfaceViewの内部で描画処理を担当してくれるようなものです。

新しくクラスを作成します。

package com.example.glsample

import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import android.opengl.GLSurfaceView

class GLRender: GLSurfaceView.Renderer {

    override fun onSurfaceCreated(gl10: GL10, eglc: EGLConfig) {

    }

    override fun onSurfaceChanged(gl10: GL10, w: Int, h: Int) {

        // 描画範囲を指定 今回は画面まるごと
        gl10.glViewport(0,0,w,h)
    }

    override fun onDrawFrame(gl10: GL10) {

        // 画面を塗りつぶす色
        gl10.glClearColor(0.5f,0.0f,0.0f,1.0f)
        // カラーバッファを使う
        gl10.glClear(GL10.GL_COLOR_BUFFER_BIT)

    }
}


これが Render です。
GLSurfaceView.Rendererを継承します。


メソッドが3つオーバーライドされています。
それぞれの実行されるタイミングです。

  • onSurfaceCreated
    GLSurfaceViewのためのメモリが確保された時
  • onSurfaceChanged
    GLSurfaceViewのサイズが変更された
  • onDrawFrame
    GLSurfaceViewが呼び続ける(描画を繰り返す)


たびたび出てくるGL10というのはopengl es へのインターフェースのようなものです。

先述したsetRendererにこのクラスのインスタンスを渡します。

これで準備が整いました。
実行してみましょう。

gl.glClearColorで指定した色で画面が塗りつぶされているはずです。


体系的にまとめることはできませんので、
ここでは四角形を表示するサンプルを作成します。

package com.example.glsample


import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import android.opengl.GLSurfaceView
import java.nio.ByteBuffer
import java.nio.ByteOrder

class GLRender: GLSurfaceView.Renderer {

    override fun onSurfaceCreated(gl10: GL10, eglc: EGLConfig) {

    }

    override fun onSurfaceChanged(gl10: GL10, w: Int, h: Int) {
        gl10.glViewport(0,0,w,h)
    }

    override fun onDrawFrame(gl10: GL10) {
        gl10.glClearColor(0.5f,0.4f,0.3f,1.0f)
        gl10.glClear(GL10.GL_COLOR_BUFFER_BIT)

        gl10.glColor4f(0.0f,0.0f,0.0f,1.0f)
        draw(gl10, 0.0f,0.0f,0.3f,0.3f)
    }

    fun draw(gl10: GL10, x: Float, y: Float, w: Float, h: Float) {
        var pos = floatArrayOf(
            x, y+h, 0.0f,
            x, y, 0.0f,
            x+w, y+h, 0.0f,
            x+w, y, 0.0f
        )

        // 頂点のためのメモリを確保します
        val bb = ByteBuffer.allocateDirect(pos.size*4)
        // バイトオーダーを設定します 環境に適した値を設定するためnativeOrder()を呼び出す
        bb.order(ByteOrder.nativeOrder())

        // ByteBufferをFloatBufferに変換して頂点を設定します。
        val fb = bb.asFloatBuffer()
        fb.put(pos)
        fb.position(0)

        // 頂点情報(位置)を有効にする 
        gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY)
        // opengl esに頂点情報をお伝えする
        gl10.glVertexPointer(3,GL10.GL_FLOAT,0,fb)
        // 描画する これが実行されて初めて描画される
        gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4)
    }
}


これを実行すると黒い四角形が表示されます。

ここではKotlin上でのOpenGLの簡単な使い方をまとめました。

OpenGL ESについては以下の参考書がお勧めです。
少し古くJavaで書かれていますが、参考になると思います。

初めてのOpenGL ES