qiitaにおいて、一連のOpenGL ES2.0の知見をまとめましたので、もしよかったらそちらもご覧ください
今回は、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); } }
で、画像を表示する時用のクラスができました!