@blog.justoneplanet.info

日々勉強

OpenGL ESで正六面体を描画する

package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

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

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        private float aspect = 0.0f;
        private int vertices = 0;
        private int indices  = 0;
        private int indicesLength;

        /**
         * onDrawFrame
         * 毎フレーム描画時に実行される
         */
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            {// カメラの転送
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();// 行列の初期化
                GLU.gluPerspective(gl, 45.0f, aspect, 0.01f, 100.0f);// 描画する空間を指定
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);// 視点の方向を指定
            }
            
            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(0.2f, 0, 0.2f, 0);// 物体の回転
            }
            
            // 頂点バッファを関連付けて
            // 物体を描画する
            GL11 gl11 = (GL11) gl;
            gl11.glDrawElements(GL10.GL_TRIANGLES, indicesLength, GL10.GL_UNSIGNED_BYTE, 0);
         }

        /**
         * onSurfaceChanged
         * surfaceのサイズが変更されたりすると実行される
         */
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            aspect = (float) width / (float) height;
            gl.glViewport(0, 0, width, height);
            
            GL11 gl11 = (GL11) gl;
            {
                int[] buffer = new int[2];
                gl11.glGenBuffers(2, buffer, 0);
                
                vertices = buffer[0];
                indices  = buffer[1];
            }
            
            {// 頂点バッファの生成と転送
                final float one = 1.0f;
                
                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };
                
                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
                
                fb.put(vertices);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, this.vertices);
                gl11.glBufferData(GL11.GL_ARRAY_BUFFER, fb.capacity() * 4, fb, GL11.GL_STATIC_DRAW);
                
                gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
            }
            
            {// インデックスバッファの生成と転送
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                indicesLength = bb.capacity();
                bb.position(0);
                
                gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, this.indices);
                gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, bb.capacity(), bb, GL11.GL_STATIC_DRAW);
            }
       }

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

GPU側にあるVertex Buffer Objectに転送することによって、毎回OpenGLのAPIを呼び出して頂点の転送をする必要がなくなるので高速に動作する。モデルの形状が変化する場合などには向かない。

■正六面体を外部ファイル化する

Cube.java

package info.justoneplanet.android.glsample.object;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

public class Cube
{
    public float posX    = 0.0f;
    public float posY    = 0.0f;
    public float posZ    = 0.0f;
    public float rotateY = 0.0f;
    public float scale   = 1.0f;
    
    public float colR = 1.0f;
    public float colG = 1.0f;
    public float colB = 1.0f;
    public float colA = 1.0f;
    
    private int mIndicesLength;
    
    public Cube(int indicesLength)
    {
        mIndicesLength = indicesLength;
    }
    
    public void drawBox(GL10 gl)
    {
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        
        gl.glTranslatef(posX, posY, posZ);
        gl.glRotatef(rotateY, 0, 1, 0);
        gl.glScalef(scale, scale, scale);
        
        gl.glColor4f(colR, colG, colB, colA);
        
        GL11 gl11 = (GL11) gl;
        gl11.glDrawElements(GL10.GL_TRIANGLES, mIndicesLength, GL10.GL_UNSIGNED_BYTE, 0);
    }
}

MainActivity.java

package info.justoneplanet.android.glsample;

import info.justoneplanet.android.glsample.object.Cube;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

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

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        private float aspect = 0.0f;
        private int vertices = 0;
        private int indices  = 0;
        private int indicesLength;

        /**
         * onDrawFrame
         * 毎フレーム描画時に実行される
         */
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            {// カメラの転送
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();// 行列の初期化
                GLU.gluPerspective(gl, 45.0f, aspect, 0.01f, 100.0f);// 描画する空間を指定
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);// 視点の方向を指定
            }
            
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            
            {
                cube0.posX = -0.5f;
                cube0.rotateY += 1.0f;
                cube0.colR = 1.0f;
                cube0.colG = 0.0f;
                cube0.colB = 1.0f;
                cube0.drawBox(gl);
            }
            {
                cube1.posX = 0.5f;
                cube1.rotateY -= 0.5f;
                cube1.colR = 0.0f;
                cube1.colG = 0.0f;
                cube1.colB = 1.0f;
                cube1.drawBox(gl);
            }
         }

        /**
         * onSurfaceChanged
         * surfaceのサイズが変更されたりすると実行される
         */
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            aspect = (float) width / (float) height;
            gl.glViewport(0, 0, width, height);
            
            GL11 gl11 = (GL11) gl;
            {
                int[] buffer = new int[2];
                gl11.glGenBuffers(2, buffer, 0);
                
                vertices = buffer[0];
                indices  = buffer[1];
            }
            
            {// 頂点バッファの生成と転送
                final float one = 1.0f;
                
                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };
                
                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
                
                fb.put(vertices);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, this.vertices);
                gl11.glBufferData(GL11.GL_ARRAY_BUFFER, fb.capacity() * 4, fb, GL11.GL_STATIC_DRAW);
                
                gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
            }
            
            {// インデックスバッファの生成と転送
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                indicesLength = bb.capacity();
                bb.position(0);
                
                gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, this.indices);
                gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, bb.capacity(), bb, GL11.GL_STATIC_DRAW);
            }
       }

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

■前後関係を修正する

前述のコードでは重なっている部分の表示が適切ではない。従って以下のようにする。

MainActivity.java

public class MainActivity extends Activity {
    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// GL_DEPTH_BUFFER_BITも追加

            // 以下省略
         }

        /**
         * onSurfaceChanged
         * surfaceのサイズが変更されたりすると実行される
         */
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            aspect = (float) width / (float) height;
            gl.glViewport(0, 0, width, height);
            gl.glEnable(GL10.GL_DEPTH_TEST);// 奥行き情報を前後関係に利用する
            
            // 以下省略
       }

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

前後関係に奥行き情報が利用されるようになったが重なった部分の表示がギザギザしたりして美しくない。これはZファイティングと呼ばれる現象であり、ハードウェアにより不自然さが異なる。このようなことがないように位置をずらす必要がある。

androidのOpenGL ESでテクスチャを貼る

■画像

以下のようにして画像をテクスチャとして貼ることができる。

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            float left   = -0.9f;
            float top    = 0.9f;
            float right  = 0.9f;
            float bottom = -0.9f;
            
            // テクスチャの描画設定=>次の描画オブジェクトに適用される
            {
                float[] uv = {
                        left, top,
                        left, bottom,
                        right, top,
                        right, bottom,
                };

                // Java => OpenGL にあたっての変換
                ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(uv);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
                gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);// UV配列をOpen GLに紐付け
            }
            
            // ポリゴンの描画
            {
                top    = -top;
                bottom = -bottom;
                float[] vertexes = {
                        left,  top,    0.0f,
                        left,  bottom, 0.0f,
                        right, top,    0.0f,
                        right, bottom, 0.0f
                };
                
                // Java => OpenGL にあたっての変換
                ByteBuffer bb = ByteBuffer.allocateDirect(vertexes.length * 4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(vertexes);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 頂点バッファの有効化
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);// 頂点バッファをOpen GLに紐付け
                gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);// 描画する
            }
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);// 描画領域を指定
            gl.glColor4f(1.0f, 0.9f, 0.9f, 1.0f);// 短形の描画色を指定
            gl.glEnable(GL10.GL_TEXTURE_2D);// テクスチャを有効にする
            
            // テクスチャ用メモリの確保
            int[] buffers = new int[1];// テクスチャ管理IDの配列
            gl.glGenTextures(1, buffers, 0);// 1枚分のメモリを確保
            gl.glBindTexture(GL10.GL_TEXTURE_2D, buffers[0]);// 1枚目を使う指定

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.chrome);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
            
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);// 縮小時のフィルタ
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);// 拡大時のフィルタ
            
            bitmap.recycle();// bitmapを破棄
        }

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

■文字列

以下のようにcanvasを利用してして文字列を貼り付けることができる。

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        private int textureName;

        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            float left   = -0.9f;
            float top    = 0.9f;
            float right  = 0.9f;
            float bottom = -0.9f;
            
            // テクスチャの描画設定=>次の描画オブジェクトに適用される
            {
                float[] uv = {
                        left, top,
                        left, bottom,
                        right, top,
                        right, bottom,
                };

                ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(uv);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
                gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
            }
            
            // ポリゴンの描画
            {
                top    = -top;
                bottom = -bottom;
                float[] vertexes = {
                        left,  top,    0.0f,
                        left,  bottom, 0.0f,
                        right, top,    0.0f,
                        right, bottom, 0.0f
                };
                
                ByteBuffer bb = ByteBuffer.allocateDirect(vertexes.length * 4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(vertexes);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
                gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
            }
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);
            gl.glColor4f(1.0f, 0.9f, 0.9f, 1.0f);
            
            Bitmap bitmap = Bitmap.createBitmap(256, 256, Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            paint.setColor(Color.WHITE);
            paint.setStyle(Style.FILL);
            canvas.drawColor(0);
            canvas.drawText("hogehogehogehogehogehogehogehogehogehoge", 0, 15, paint);
            
            gl.glEnable(GL10.GL_TEXTURE_2D);// テクスチャを有効にする
            int[] buffers = new int[1];
            gl.glGenTextures(1, buffers, 0);
            textureName = buffers[0];
            
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
            
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
            
            bitmap.recycle();
        }

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

■座標

右上が(x, y) = (1.0, 1.0)で、左下が(x, y) = (-1.0, -1.0)となっていると非常に扱いにくい場合もある。以下のようにすることでピクセルに変換できる。

@Override
public void onDrawFrame(GL10 gl) {
    gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
    int x = 0;
    int y = 0;
    int width = 512;
    int height = 512;
    {
        float left   = ((float) x / (float) textureWidth);
        float top    = ((float) y / (float) textureHeight);
        float right  = left + ((float) width  / (float) textureWidth);
        float bottom = top  + ((float) height / (float) textureHeight);
        
        float[] uv = {
                left, top,
                left, bottom,
                right, top,
                right, bottom,
        };
        ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer fb = bb.asFloatBuffer();
        fb.put(uv);
        fb.position(0);
        
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
    }
    {
        float left   = ((float) x / (float) screenWidth)  * 2.0f - 1.0f;
        float top    = ((float) y / (float) screenHeight) * 2.0f - 1.0f;
        float right  = left + ((float) width  / (float) screenWidth)  * 2.0f;
        float bottom = top  + ((float) height / (float) screenHeight) * 2.0f;
        
        top    = -top;
        bottom = -bottom;
        
        float[] positions = {
                left,  top,    0.0f,
                left,  bottom, 0.0f,
                right, top,    0.0f,
                right, bottom, 0.0f
        };
        
        ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer fb = bb.asFloatBuffer();
        fb.put(positions);
        fb.position(0);
        
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        
    }
    counter++;
}

■まとめ

JavaScriptでCanvasを操作してアニメーションする感じに似ている。もっと言うとPhotoshopで作業をする感じにも似ている。

OpenGL ESメモ

コードを書いておく。ただそれだけ。

package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;



    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();
                
                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 0, 10.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }
            
            // vertices
            {
                final float one = 1.0f;
                
                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };
                
                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
                
                fb.put(vertices);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
            }
            
            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);// 回転
            }
            
            {
                final byte[] indices = new byte[]{0, 1, 2, 3, 6, 7, 4, 5, 0, 1};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(0, 1, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
            
            {
                final byte[] indices = new byte[]{1, 5, 3, 7};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(0, 0, 1, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
            
            {
                final byte[] indices = new byte[]{0, 2, 4, 6};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(1, 0, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
       }
    }
}
package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;



    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();
                
                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }
            
            // vertices
            {
                final float one = 1.0f;
                
                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };
                
                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
                
                fb.put(vertices);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
            }
            
            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);// 回転
            }
            
            {
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(1, 1, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
       }
    }
}
package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;



    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }
    
    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }
    
    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }
    
    private class Renderer implements GLSurfaceView.Renderer
    {
        private float aspect = 0.0f;
        private int vertices = 0;
        private int indices  = 0;
        private int indicesLength;

        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            
            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();
                
                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }
            
            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);
            }
            
            GL11 gl11 = (GL11) gl;
            gl11.glDrawElements(GL10.GL_TRIANGLES, indicesLength, GL10.GL_UNSIGNED_BYTE, 0);
            
         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            aspect = (float) width / (float) height;
            gl.glViewport(0, 0, width, height);
            
            GL11 gl11 = (GL11) gl;
            {
                int[] buffer = new int[2];
                gl11.glGenBuffers(2, buffer, 0);
                
                vertices = buffer[0];
                indices = buffer[1];
            }
            
            // vertices
            {
                final float one = 1.0f;
                
                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };
                
                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
                
                fb.put(vertices);
                fb.position(0);
                
                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, this.vertices);
                gl11.glBufferData(GL11.GL_ARRAY_BUFFER, fb.capacity() * 4, fb, GL11.GL_STATIC_DRAW);
                
                gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
            }
            
            {
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                indicesLength = bb.capacity();
                bb.position(0);
                
                gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, this.indices);
                gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, bb.capacity(), bb, GL11.GL_STATIC_DRAW);
            }
       }

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