
Androidの頂点属性のインデックスの固定化をしてキューブを描くサンプル#tryGLES2004


頂点情報の位置をこちらから指定して固定化する
0なら頂点座標 1なら頂点色 2なら法線 のようにする
glBindAttribLocationを使うと頂点内容のインデックスを
こちらから指定することができる
OpenGL ES2.0を使ってキューブを描く
VBOを使って頂点データの最適化をする
頂点座標と頂点カラーを持たせる
シェーダーのソースとJavaのソースを定数を使ってつなぐ
大事なところ
glGetUniformLocationをglBindAttribLocationに変更
関連項目
VBO
Vertex Buffer Object
glVertexAttribPointer
glDrawElements
glEnableVertexAttribArray
glBindAttribLocation
頂点内容の固定化
開発環境
Eclipse IDE バージョン: 3.7 Indigo Service Release 1
ターゲットプラットフォーム: 2.3.3
API レベル: 10
キーワード:頂点内容のインデックス
package trial.sample.trygles2004; import java.nio.Buffer; 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 android.app.Activity; import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; public class TryGLES2004Activity extends Activity { private RenderSurfaceView mRenderView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.mRenderView = (RenderSurfaceView)this .findViewById(R.id.rendersurface1); } @Override public void onResume() { super.onResume(); this.mRenderView.onResume(); } @Override public void onPause() { super.onPause(); this.mRenderView.onPause(); } } /////////////////////////////////////////////////////////////////////////// //GLSurfaceViewの拡張 class RenderSurfaceView extends GLSurfaceView { public RenderSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); this.setEGLContextClientVersion(2); // レンダラ―の設定 this.setRenderer(new SurfaceRenderer()); } public RenderSurfaceView(Context context) { super(context); // OpenGL ES2.0を使うためにバージョンを指定する this.setEGLContextClientVersion(2); this.setRenderer(new SurfaceRenderer()); } } /////////////////////////////////////////////////////////////////////////// //ビュー用のレンダラ― class SurfaceRenderer implements GLSurfaceView.Renderer { // 頂点内容のインデックス をこちらから指定する public static final int ATTRIBUTE_POSITION_LOCATION = 0; public static final int ATTRIBUTE_COLOR_LOCATION = 1; public static final String ATTRIBUTE_POSITION = "a_position"; public static final String ATTRIBUTE_COLOR = "a_color"; public static final String UNIFORM_MODELVIEWMATRIX = "u_modelViewMatrix"; public static final String UNIFORM_PROJECTIONMATRIX = "u_projectionMatrix"; public static final String VARYING_COLOR = "v_color"; private float mAspect; // アスペクト比 private float mModelRot; // モデルの回転 // 描画するためのもの private int mVertexShaderID; // 頂点シェーダーID private int mFragmentShaderID; // フラグメントシェーダーID private int mProgramID; // プログラムオブジェクトID // シェーダーに値を送るためのハンドル private int mLocModelView; private int mLocProj; // VBO の管理番号 private int mVertexBufferID; // 頂点バッファ private int mIndexBufferID; // インデックスバッファ // 各行列 private float[] mModelView = new float[16]; // モデルビュー private float[] mProj = new float[16]; // プロジェクション /////////////////////////////////////////////////////////////////////////// /** 最初に呼ばれる */ public void onSurfaceCreated(GL10 gl, EGLConfig config) { // シェーダーを初期化する this.initShader(); // こちから指定した 頂点内容のインデックス を有効にする // 頂点配列を有効にする GLES20.glEnableVertexAttribArray(ATTRIBUTE_POSITION_LOCATION); // 頂点カラー を有効にする GLES20.glEnableVertexAttribArray(ATTRIBUTE_COLOR_LOCATION); // デプスバッファを有効にする GLES20.glEnable(GLES20.GL_DEPTH_TEST); // VBO を初期化する this.initVBO(); } // ///////////////////////////////////////////////////////////////////////// // VBOを登録する private void initVBO() { // 頂点座標 + 頂点カラー // 頂点バッファから VBO を作る float[] vertices = { // 座標(x, y, z) 頂点色(r, g, b, a) 1.0f, 1.0f, 1.0f, 1.f, 1.f, 1.f, 1.f, 1.0f, 1.0f,-1.0f, 1.f, 0.f, 0.f, 1.f, -1.0f, 1.0f, 1.0f, 0.f, 1.f, 0.f, 1.f, -1.0f, 1.0f,-1.0f, 0.f, 0.f, 1.f, 1.f, 1.0f,-1.0f, 1.0f, 1.f, 1.f, 0.f, 1.f, 1.0f,-1.0f,-1.0f, 1.f, 0.f, 1.f, 1.f, -1.0f,-1.0f, 1.0f, 0.f, 1.f, 1.f, 1.f, -1.0f,-1.0f,-1.0f, 0.f, 0.f, 0.f, 1.f, }; FloatBuffer vertexBuffer = this.makeFloatBuffer(vertices); // 頂点データ(座標、法線、色、テクスチャ座標)には // GL_ARRAY_BUFFERを指定する this.mVertexBufferID = this.makeVBO( vertexBuffer, 4, GLES20.GL_ARRAY_BUFFER); // インデックスバッファから VBO を作る byte[] indices = { 0,1,2,3, 2,3,6,7, 6,7,4,5, 4,5,0,1, 1,5,3,7, 0,2,4,6, }; ByteBuffer indexBuffer = this.makeByteBuffer(indices); // インデックスの登録には // GL_ELEMENT_ARRAY_BUFFERを使う this.mIndexBufferID = this.makeVBO( indexBuffer, 1, GLES20.GL_ELEMENT_ARRAY_BUFFER); } // ///////////////////////////////////////////////////////////////////////// // 各バッファから VBO へ変換する private int makeVBO(Buffer buffer, int size, int target) { int[] hardwareIDContainer= { -1 }; // ハードウェア側の準備 GLES20.glGenBuffers(1, hardwareIDContainer, 0); GLES20.glBindBuffer(target, hardwareIDContainer[0]); GLES20.glBufferData(target, buffer.capacity() * size, buffer, GLES20.GL_STATIC_DRAW); return hardwareIDContainer[0]; } // ///////////////////////////////////////////////////////////////////////// // シェーダーを初期化する private void initShader() { // 頂点カラー 付き頂点シェーダーのコンパイル String vertexCode = "uniform mat4 " + UNIFORM_MODELVIEWMATRIX + ";"+ "uniform mat4 " + UNIFORM_PROJECTIONMATRIX + ";"+ "attribute vec4 " + ATTRIBUTE_POSITION + ";"+ "attribute vec4 " + ATTRIBUTE_COLOR + ";"+ "varying vec4 " + VARYING_COLOR + ";" + "void main(){"+ " gl_Position = " + UNIFORM_PROJECTIONMATRIX + " * " + UNIFORM_MODELVIEWMATRIX + " * " + ATTRIBUTE_POSITION + ";"+ " " + VARYING_COLOR + " = " + ATTRIBUTE_COLOR +";"+ "}"; this.mVertexShaderID = this.compileShader( GLES20.GL_VERTEX_SHADER, vertexCode); // 頂点カラー 付きフラグメントシェーダーのコンパイル String fragmentCode = "precision mediump float;"+ "varying vec4 " + VARYING_COLOR + ";" + "void main(){"+ " gl_FragColor = " + VARYING_COLOR + ";"+ "}"; this.mFragmentShaderID = this.compileShader( GLES20.GL_FRAGMENT_SHADER, fragmentCode); // プログラムオブジェクトを作る this.mProgramID = GLES20.glCreateProgram(); GLES20.glAttachShader(this.mProgramID, this.mVertexShaderID); GLES20.glAttachShader(this.mProgramID, this.mFragmentShaderID); // 頂点内容のインデックス をシェーダー変数と関連付ける // 頂点座標 GLES20.glBindAttribLocation(this.mProgramID, ATTRIBUTE_POSITION_LOCATION, ATTRIBUTE_POSITION); // 頂点カラー GLES20.glBindAttribLocation(this.mProgramID, ATTRIBUTE_COLOR_LOCATION, ATTRIBUTE_COLOR); GLES20.glLinkProgram(this.mProgramID); // シェーダーに値を送るためのハンドルを取り出す this.mLocModelView = GLES20.glGetUniformLocation( this.mProgramID, UNIFORM_MODELVIEWMATRIX); this.mLocProj = GLES20.glGetUniformLocation( this.mProgramID, UNIFORM_PROJECTIONMATRIX); // プログラムオブジェクトを使い始める GLES20.glUseProgram(this.mProgramID); } /////////////////////////////////////////////////////////////////////////// /** サーフェイスのサイズ変更時とかに呼ばれる */ public void onSurfaceChanged(GL10 gl, int width, int height) { // ビューポートの再設定 GLES20.glViewport(0, 0, width, height); // アスペクト比 this.mAspect = (float)width / (float)height; } /////////////////////////////////////////////////////////////////////////// /** マイフレーム呼ばれるやつ */ public void onDrawFrame(GL10 gl) { // 画面をクリア GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); // プロジェクション行列 Matrix.setIdentityM(this.mProj, 0); this.Perspective(this.mProj, 45.f, this.mAspect, 1.0f, 100.f); // シェーダーに送信 GLES20.glUniformMatrix4fv(this.mLocProj, 1, false, this.mProj, 0); // ビュー行列 Matrix.setIdentityM(this.mModelView, 0); Matrix.setLookAtM(this.mModelView, 0, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); // モデル変換 Matrix.rotateM(this.mModelView, 0, this.mModelRot, 1.0f, 1.0f, 0.0f); // シェーダーにモデルビュー行列を送信 GLES20.glUniformMatrix4fv(this.mLocModelView, 1, false, this.mModelView, 0); this.mModelRot++; // VBO での描画 // 頂点バッファのセット GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.mVertexBufferID); // 頂点内容のインデックス で、各値の場所を指定する GLES20.glVertexAttribPointer(ATTRIBUTE_POSITION_LOCATION, 3, GLES20.GL_FLOAT, false, 7 * 4, 0); GLES20.glVertexAttribPointer(ATTRIBUTE_COLOR_LOCATION, 4, GLES20.GL_FLOAT, false, 7 * 4, 3 * 4); // インデックスバッファの指定 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.mIndexBufferID); // キューブを描く // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 0); // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 4); // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 8); // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 12); // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 16); // 面を描く GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_BYTE, 20); } // ///////////////////////////////////////////////////////////////////////// // プロジェクション行列を作る private void Perspective(float[] out, float fov, float aspect, float near, float far) { float top = near * (float)Math.tan(Math.toRadians(fov)); float bottom = -top; float left = bottom * aspect; float right = top * aspect; Matrix.frustumM(out, 0, left, right, bottom, top, near, far); } /////////////////////////////////////////////////////////////////////////// // FloatBufferを作って値をセットする private FloatBuffer makeFloatBuffer(float[] values) { // バッファを作る FloatBuffer fb = ByteBuffer.allocateDirect(values.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); // 作ったバッファに値をセットしておく fb.put(values) .position(0); return fb; } /////////////////////////////////////////////////////////////////////////// // IntBufferを作って値をセットする private ByteBuffer makeByteBuffer(byte[] values) { ByteBuffer buf = ByteBuffer.allocateDirect(values.length) .order(ByteOrder.nativeOrder()); buf.put(values) .position(0); return buf; } /////////////////////////////////////////////////////////////////////////// // シェーダーのソースコードをコンパイルする private int compileShader(int type, String code) { final int shaderId = GLES20.glCreateShader(type); if (shaderId == 0) { // シェーダーの領域確保に失敗した Log.d("compileShader", "領域確保に失敗"); return -1; } // シェーダーをコンパイル GLES20.glShaderSource(shaderId, code); GLES20.glCompileShader(shaderId); // コンパイルが成功したか調べる int[] res = new int[1]; GLES20.glGetShaderiv(shaderId, GLES20.GL_COMPILE_STATUS, res, 0); if (res[0] == 0) { // 失敗してる Log.d("compileShader", GLES20.glGetShaderInfoLog(shaderId)); return -1; } return shaderId; } }
AndroidのEditTextにアプリ起動直後にソフトウェアキーボードを出すサンプ... AndroidのEditTextに入力できる文字列をInputFilterで制限するサンプル#tr...