opengl es2を勉強する。その2 画像を描く

前回から、紹介してる内容は、opengl使ってるっていう人には、違和感があるかもしれないのですが、自分としては、

・シンプルに書いて、必要に応じて調べる

という事を目的に書いてます。

初心者丸出しだけど下記みたいになります。

 

device-2015-07-07-170612

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の頃はメモリの為に捨てる必要もあったかと思うので、そのあたりも含めて整理が必要そうです。

 

前後の記事

前の記事:

次の記事:

関連の記事

コメントの投稿

  • サイト内検索

新作アプリの紹介

関連サイトの紹介

アンドロイドアプリ開発TIPS
きぐるみカメラ
ふらいぱん
アンドロイドのデザイン集
Page top↑