android openGL ES 20 投影、相机画等边三角形和正方形

本文参照:http://hukai.me/android-training-course-in-chinese/graphics/opengl/projection.html
投影(Projection):投影会基于显示出来的GLSurfaceView的长和宽,来调整绘图对象的坐标。如果没有投影计算,那么用OpenGL ES绘制的对象会由于其长宽比例和View窗口比例的不一致而发生形变。
发生时间:一般仅当OpenGL View的比例在渲染器的onSurfaceChanged()方法中建立或发生变化时才会被计算
相机视角(Camera View):基于一个虚拟相机位置改变绘图对象的坐标。事实上,OpenGL ES并没有定义一个实际的相机对象,而是提供一些方法,通过绘图对象的变换来模拟相机视角。
发生时间:一个相机视角可以仅在建立GLSurfaceView时计算一次,也可以进行动态调整。
关于openGL矩阵的一些函数讲解可参照:
http://blog.sina.com.cn/s/blog_a23d30f101018gl4.html
openGL坐标系如图
android openGL ES 20 投影、相机画等边三角形和正方形_第1张图片

这份代码解决了上篇文章中画出来的三角形变形的问题,修改如下:
在MyGL20Renderer类中添加

 // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];

并修改onDrawFrame和onSurfaceChanged方法:

 public void onDrawFrame(GL10 unused) {
        // 重绘背景色
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        // 设置相机的位置。参数:要填充的矩阵;偏移;相机的x,y,z坐标;目标的x,y,z坐标;视觉向量x,y,z
        //关于这个函数的更详细讲解可参照http://blog.csdn.net/a7178077/article/details/38014373
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        // 参数说明:mMVPMatrix为mProjectionMatrix和mViewMatrix相乘得到,其他三个0均为偏移
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        //绘制三角形
        triangle.draw(mMVPMatrix);
        //绘制矩形
//        square.draw();
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;

        // 这个投影矩阵是在onDrawFrame()方法中应用于目标对象坐标的
        //Matrix.frustumM:凸透镜眼睛
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }

然后修改Util类中原本的VertexShaderCode这个变量的值:

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

修改第一个draw方法:

 /**
     * @param coords_per_vertex 每个顶点的坐标数
     * @param vertexBuffer      浮点缓冲区
     * @param color             颜色数组,数组的四个数分别为图形的RGB值和透明度
     */
    public void draw(int coords_per_vertex, FloatBuffer vertexBuffer, float color[],float mvpMatrix[]) {
        //获取程式
        int program = getProgram();

        //得到处理到顶点着色器的vPosition成员
        int vPositionHandler = GLES20.glGetAttribLocation(program, "vPosition");

        // 启用一个指向图形的顶点数组的handle
        GLES20.glEnableVertexAttribArray(vPositionHandler);

        // 准备坐标数据
        GLES20.glVertexAttribPointer(vPositionHandler, coords_per_vertex,
                GLES20.GL_FLOAT, false,
                LENGTH * coords_per_vertex, vertexBuffer);

        // 得到处理到片段着色器的vPosition成员
        int mColorHandle = GLES20.glGetUniformLocation(program, "vColor");

        // 设置颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // get handle to shape's transformation matrix
        int MVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");

        // Pass the projection and view transformation to the shader
        GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);

        // 绘制三角形比较简单,这里采用glDrawArrays方法(默认是逆时针方向)
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

        // 禁用指向图形的顶点数组
        GLES20.glDisableVertexAttribArray(MVPMatrixHandle);
    }

修改Triangle类中的draw方法:

  public void draw(float matrix[]){
        new Util().draw(COORDS_PER_VERTEX,vertexBuffer,color,matrix);
    }

至此,OK了,终于显示出了等边三角形。如图:
android openGL ES 20 投影、相机画等边三角形和正方形_第2张图片

正方形的代码与此类似,只要稍微修改Util类中的第二个draw方法即可。

    // Pass the projection and view transformation to the shader
        GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);

        // 绘制图形
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

并在方法参数末尾添加float mvpMatrix[]就行

你可能感兴趣的:(android,openGL)