qiitaにおいて、一連のOpenGL ES2.0の知見をまとめましたので、もしよかったらそちらもご覧ください
前回から、紹介してる内容は、opengl使ってるっていう人には、違和感があるかもしれないのですが、自分としては、
・シンプルに書いて、必要に応じて調べる
という事を目的に書いてます。
初心者丸出しだけど下記みたいになります。
OpenGLを使ってみましょうって書いてあって、説明不足で不明点大量の記事や本に辟易してしまったので、なるべくシンプルに書いてます。
前回の
opengl es2を勉強する。その1 三角形を書いて動かす。
をそのまま使います。追加して書いていきますね。
Spriteというクラスで画像を描くとすると
public class GLRenderer implements GLSurfaceView.Renderer { Context ctx; public GLRenderer(Context _ctx){ ctx = _ctx; } Sprite sprite; Triangle triangle; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { triangle = new Triangle(); sprite = new Sprite(ctx,gl); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override public void onDrawFrame(GL10 gl) { GLES20.glClearColor(0.0f, 0.0f, 0.7f, 1); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); triangle.draw(); sprite.draw(); } private void callLog(String str){ Log.e("LOG",str); } public void onPause(){ } public void onResume(){ } }
という形でレンダラーの方をまとめます。で描画用のクラスの方は
public class Sprite { //画面の方の座標 zも含む private float vertices[] = { 0.0f, 0.0f,0.0f, 0.0f, 1.0f,0.0f, 1.0f, 0.0f,0.0f, 1.0f, 1.0f,0.0f }; //画像の方の座標 public static float uvs[] = new float[] { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; public FloatBuffer vertexBuffer; public ShortBuffer drawListBuffer; public FloatBuffer uvBuffer; //最もシンプルなシェーダー public final String vertexShaderCode = "attribute vec4 vPosition;" + "attribute vec2 a_texCoord;" + "varying vec2 v_texCoord;" + "void main() {" + " gl_Position = vPosition;" + " v_texCoord = a_texCoord;" + "}"; public final String fragmentShaderCode = "precision mediump float;" + "varying vec2 v_texCoord;" + "uniform sampler2D s_texture;" + "void main() {" + " gl_FragColor = texture2D( s_texture, v_texCoord );" + "}"; public static int loadShader(int type, String shaderCode){ int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } int shaderProgram; int[] texture; Context ctx; public Sprite(Context _ctx){ ctx = _ctx; setupImage(); //頂点座標をバッファーに変換 ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); //ここからシェーダーを使うっていう、定形 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); } private void setupImage(){ //画像側の頂点座標をバッファーに変換 ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4); bb.order(ByteOrder.nativeOrder()); uvBuffer = bb.asFloatBuffer(); uvBuffer.put(uvs); uvBuffer.position(0); texture = new int[1]; //Bitmapは自分で作ったクラスで持ってきていますが、自分の方法で用意してください。 //Openglなのでサイズは128*128-1024*1024とか2の累乗の正方形にしましょう。 //詳しく調べてませんがes1の時に累乗の正方形でないと出ない端末と出る端末がありました。 Bitmap bitmap = Util.loadBitmapFromAsset(ctx,"256_2.png"); GLES20.glGenTextures(1,texture,0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); // 拡大縮小の時のフィルターの設定 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); // ちょっとわからないけど何かの設定 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); // 画像をテクスチャに登録 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); Log.e("CHECLK", "ID:" + texture[0]); } public void draw(){ GLES20.glUseProgram(shaderProgram); // シェーダーの準備(図形側) int mPositionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition"); // シェーダー:ON GLES20.glEnableVertexAttribArray(mPositionHandle); //シェーダーの準備(テクスチャ側) int mTexCoordLoc = GLES20.glGetAttribLocation(shaderProgram,"a_texCoord" ); // シェーダー:ON GLES20.glEnableVertexAttribArray(mTexCoordLoc ); //////////////////////////////////START //vertexBufferをデータ列から頂点データという解釈に変換 GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); //uvBufferをデータ列から頂点データという解釈に変換 GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer); // 描画に利用をする画像のデータをする GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); // 描画する。何で描くのかは、「関数内で登録してある」という暗黙の了解的な。 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); //////////////////////////////////END // シェーダー:OFF GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTexCoordLoc); } }
で説明は、関数内部に書いてあります。画像のデータはテクスチャっていうのでbindする事で使えるのですが、es1の頃はメモリの為に捨てる必要もあったかと思うので、そのあたりも含めて整理が必要そうです。