OpenGL ES 2.0でゲームを作ったので、どんな動きが可能か、確認の為でも見てみてください。
ひらがな戦記
2Dに関しては、ライティングなどもしないので、特に知見などもなくできるのですが、3Dになってくるとライティングや計算式などを勉強する必要が出てくるような認識でした。
※一部コメントで頂いた内容を抜粋します。失礼しました
うちの環境(Android5.1.1, Xperia Z3)でサンプルを動かしたところ三角形が表示されなかったので
GLES20.glVertexAttribPointer(positionAttrib,vertices.length, GLES20.GL_FLOAT, false, 0, vertexBuffer);
を
GLES20.glVertexAttribPointer(positionAttrib, 3, GLES20.GL_FLOAT, false, 3 *4, vertexBuffer);
のようにしたら表示されるようになりました。
AndroidでOpenGL ES2.0の入門
アンドロイドが遅い。「SurfaceViewを用いると早い!」という噂もありますが、「遅い」ので、OpenGLを使っています。ES1.0で十分ですが、古い言語を使う弊害の可能性があります。リファレンスもほとんどなかったので、書いてみました。間違っていたらすいません。
Manifestファイル
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
を追加しました。これを書かないと、OpenGL ES2.0に対応してない端末でもインストールできてしまうだけです。
Activityファイル
レンダリングをGLSurfaceViewに設定しています。setEGLContextClientVersion(2);でバージョンの指定(ES2.0)をします。setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);でモードを指定しています。絶え間なくレンダリング(RENDERMODE_CONTINUOUSLY)を設定
※GLRendererというのは後ほど実装
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setEGLContextClientVersion(2);
mRenderer = new GLRenderer(getApplicationContext());
glSurfaceView.setRenderer(mRenderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
setContentView(glSurfaceView);
}
Renderファイル
別クラスで描画を書いてます、書く対象毎にshaderを用意したり設定をするので個々に設定を書けるように、Triangleというクラスを作っています。背景色の設定と、毎回ステージの上書きを指定してあります
※Triangleというのは後ほど実装
public class GLRenderer implements GLSurfaceView.Renderer {
public GLRenderer(){
}
Triangle triangle;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
triangle = new Triangle();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
@Override
public void onDrawFrame(GL10 unused) {
//背景色(R,G,B,ALPHA)
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
triangle.draw();
}
}
図形クラス
準備工程(コンストラクタでは)Triangle ()
- shaderを準備する
- shaderをコンパイルする
コンパイル手順 loadShader()
- 文字列をシェーダーとしてコンパイル
- programという名前でshaderを保持する
- programをリンクする。
描画手順 draw()
- 使うプログラムを選択
- プログラムより座標系を取得
- 図形の頂点座標を準備
- 頂点座標をバッファーに変換
- バッファー情報をshaderと合わせる
- 描画する
- 終了
描画方式は三角形を書いていく形式になります。
public class Triangle {
//シンプルなシェーダー
public final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
//シンプル色は自分で指定(R,G,B ALPHA)指定
public final String fragmentShaderCode =
"precision mediump float;" +
"void main() {" +
" gl_FragColor =vec4(1.0, 0.0, 0.0, 1.0);" +
"}";
private int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private int shaderProgram;
public Triangle(){
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertexShader);
GLES20.glAttachShader(shaderProgram, fragmentShader);
GLES20.glLinkProgram(shaderProgram);
}
public void draw(){
GLES20.glUseProgram(shaderProgram);
int positionAttrib = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
GLES20.glEnableVertexAttribArray(positionAttrib);
float vertices[] = {
0.0f, 0.5f, 0.0f,//三角形の点A(x,y,z)
-0.5f, -0.5f, 0.0f,//三角形の点B(x,y,z)
0.5f, -0.5f, 0.0f//三角形の点C(x,y,z)
};
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(positionAttrib,vertices.length, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertices.length/3);
GLES20.glDisableVertexAttribArray(positionAttrib);
}
}
完成
次の一手
シンプルに作っています。入門と言いながら、複雑な「入門」が多くありました。そういったものと差異を見て、違いから、該当の関数などの役割を調べて、できる事を増やしていくと良いかと思います。