opengl es2を勉強する。その9 shaderにマトリックスを用いる

今回は、matrixを用いてshaderを作ってみます。

そもそも最初に、

http://androidblog.reindustries.com/a-real-open-gl-es-2-0-2d-tutorial-part-1/

で勉強していたのに、matrixと、shaderの関係性がイマイチわかってなかったのですが、

今であれば、matrixを作って、uniformとしてshaderの中に突っ込むという動作をしていたのがわかります。

なので、今回はマトリックスを作って、適合をしてみます。

マトリックスは下記にしました

// 画面の座標系を作成
Matrix.orthoM(mtrxProjection, 0,
        0f, width,//左端→右端
        height, 0.0f, //下端→上端
        -1, 1//手前→奥
);

//カメラの向きを作成
Matrix.setLookAtM(mtrxView, 0,
        0f, 0f, 1f,//カメラ位置
        0f, 0f, 0f,//カメラの向き
        0f, 1.0f, 0.0f//カメラの頭
);

//上記2つを合算。
Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

座標系として、OpenGLは左下が基準となっていますが、左上に基準を変更して、スケールを解像度に揃えました。

でshaderを

public final String vertexShaderCode =
        "uniform    mat4        uMVPMatrix;" +
        "attribute  vec4 vPosition;" +
                "void main() {" +
                "  gl_Position = uMVPMatrix*vPosition;" +
                "}";

みたいにuMVPMatrixっていうのを考えて、

GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix"), 1, false, mtrxProjectionAndView, 0);

ってして、する事で、マトリックスを適応したシェーダーにする事で、思い通りの座標になります。

ソースコードは下記です

public class GLRenderer implements GLSurfaceView.Renderer {

    Context ctx;
    public GLRenderer(Context _ctx){
        ctx = _ctx;
    }

    Triangle triangle;
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {


        triangle = new Triangle();
    }

    // Our matrices
    private final float[] mtrxProjection = new float[16];
    private final float[] mtrxView = new float[16];
    private final float[] mtrxProjectionAndView = new float[16];

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


        for(int i=0;i<16;i++) {
            mtrxProjection[i] = 0.0f;
            mtrxView[i] = 0.0f;
            mtrxProjectionAndView[i] = 0.0f;
        }

        // 画面の座標系を作成
        Matrix.orthoM(mtrxProjection, 0,
                0f, width,//左端→右端
                height, 0.0f, //下端→上端
                -1, 1//手前→奥
        );

        //カメラの向きを作成
        Matrix.setLookAtM(mtrxView, 0,
                0f, 0f, 1f,//カメラ位置
                0f, 0f, 0f,//カメラの向き
                0f, 1.0f, 0.0f//カメラの頭
        );

        //上記2つを合算。
        Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

    }

    @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(mtrxProjectionAndView);
    }


    private void callLog(String str){
        Log.e("LOG",str);
    }

    public void onPause(){

    }

    public void onResume(){

    }
}

で三角形の記述は

public class Triangle {

    //三角形の頂点座標をx,y,zで記述
    private float vertices[] = {
        0f, 0f, 0.0f,
        50f, 150f, 0.0f,
        150f, 50f, 0.0f
    };
    //色データを赤、緑、青、アルファで記述
    float[] color = new float[]{0.0f,0.6f,1.0f,1f};

    public final String vertexShaderCode =
            "uniform    mat4        uMVPMatrix;" +
            "attribute  vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix*vPosition;" +
                    "}";
    public final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    public static int loadShader(int type, String shaderCode){
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }

    private  int shaderProgram;
    FloatBuffer vertexBuffer;


    public Triangle(){
        //頂点座標をバッファーに変換
        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);



    }

    public void draw(float[] m){

        //利用するシェーダーの選択
        GLES20.glUseProgram(shaderProgram);

        // シェーダーの準備
        int positionAttrib = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        // シェーダー:ON
        GLES20.glEnableVertexAttribArray(positionAttrib);

        // vertexBufferをデータ列から頂点データという解釈に変換
        //GLES20.glVertexAttribPointer(mPositionHandle, 頂点の数, GLES20.GL_FLOAT, 正規化をする, オフセット, vertexBuffer);
        GLES20.glVertexAttribPointer(positionAttrib,vertices.length/3, GLES20.GL_FLOAT, false, 0, vertexBuffer);

        //ユニフォーム変数にアクセスの準備

        //色情報をユニフォーム変数に変換
        GLES20.glUniform4fv(GLES20.glGetUniformLocation(shaderProgram, "vColor"), 1, color, 0);


        GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix"), 1, false, m, 0);

        //第二引数はオフセット、第三引数は、頂点の数
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertices.length/3);

        // シェーダー:OFF
        GLES20.glDisableVertexAttribArray(positionAttrib);

    }

}

で、画像を表示する時用のクラスができました!

前後の記事

前の記事:

次の記事:

関連の記事

コメントの投稿

  • サイト内検索

新作アプリの紹介

関連サイトの紹介

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