Android Opengl es 2.0 画圆,网上说原理的文章挺多的,但要么是1.0的实现,要么无法跑起来。发现一个可以跑起来的方案:http://www.java2s.com/Open-Source/Android_Free_Code/OpenGL/Shape/mkabatek_androidOpenGLShapes.htm。在此记录一下。

原文中由于没有进行坐标转换,所以画出来的圆不是正圆,下面的代码对此进行了更正。当然,你也可以用其他方式变换,比如:http://androidblog.reindustries.com/a-real-open-gl-es-2-0-2d-tutorial-part-1/上面的变换方式。

主要类如下:

Circle.java:

import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES20;import android.util.Log;public class Circle {    static final int COORDS_PER_VERTEX = 3;    private int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle;    private FloatBuffer vertexBuffer;    private float vertices[];    float color[] = {0.00f, 0.76953125f, 0.22265625f, 1.0f};    private final int vertexCount = 364 * 3 / COORDS_PER_VERTEX;    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex    private final String vertexShaderCode ="attribute vec4 vPosition;"            + "uniform mat4 uMVPMatrix;"            + "void main() {"            + "  gl_Position = uMVPMatrix * vPosition;"            + "}";    private final String fragmentShaderCode =            "precision mediump float;" +                    "uniform vec4 vColor;" +                    "void main() {" +                    "  gl_FragColor = vColor;" +                    "}";    public Circle() {        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);        vertices = new float[364 * 3];        vertices[0] = 0;        vertices[1] = 0;        vertices[2] = 0;        for (int i =1; i <364; i++){            vertices[(i * 3)+ 0] = (float) (0.5 * Math.cos((3.14/180) * (float)i ));            vertices[(i * 3)+ 1] = (float) (0.5 * Math.sin((3.14/180) * (float)i ));            vertices[(i * 3)+ 2] = 0;        }        Log.v("Thread", "" + vertices[0] + "," + vertices[1] + "," + vertices[2]);        ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);        vertexByteBuffer.order(ByteOrder.nativeOrder());        vertexBuffer = vertexByteBuffer.asFloatBuffer();        vertexBuffer.put(vertices);        vertexBuffer.position(0);        mProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program        GLES20.glLinkProgram(mProgram);    }    public void draw(float[] mvpMatrix) {        // Add program to OpenGL ES environment        GLES20.glUseProgram(mProgram);        // get handle to vertex shader's vPosition member        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");        // Enable a handle to the triangle vertices        GLES20.glEnableVertexAttribArray(mPositionHandle);        // Prepare the triangle coordinate data        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,                GLES20.GL_FLOAT, false,                vertexStride, vertexBuffer);        // get handle to fragment shader's vColor member        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");        // Set color for drawing the triangle        GLES20.glUniform4fv(mColorHandle, 1, color, 0);        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");        // Apply the projection and view transformation        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);        // Draw the circle        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);        // Disable vertex array        GLES20.glDisableVertexAttribArray(mPositionHandle);    }}

MyGLRenderer.java

import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLES20;import android.opengl.GLSurfaceView;import android.opengl.Matrix;import android.util.Log;public class MyGLRenderer implements GLSurfaceView.Renderer {    private static final String TAG = "MyGLRenderer";    // initialize a circle    Circle mCircle;    //Our screenresolution    float mScreenWidth = 1920;    float mScreenHeight = 1080;    // 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];    public void onSurfaceCreated(GL10 unused, EGLConfig config) {        // Set the background frame color        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);        mCircle = new Circle();    }    public void onDrawFrame(GL10 unused) {        // Redraw background color        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);        mCircle.draw(mMVPMatrix);    }    public void onSurfaceChanged(GL10 unused, int width, int height) {        mScreenWidth = width;        mScreenHeight = height;        GLES20.glViewport(0, 0, width, height);        // Clear our matrices        for (int i = 0; i < 16; i++) {            mProjectionMatrix[i] = 0.0f;            mViewMatrix[i] = 0.0f;            mMVPMatrix[i] = 0.0f;        }        float ratio = (float) width / height;        // 在onDrawFrame()方法中,将投影矩阵应用到对象的坐标        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);        // Set the camera position (View matrix)        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);        // Calculate the projection and view transformation        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);    }    public static int loadShader(int type, String shaderCode) {        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)        int shader = GLES20.glCreateShader(type);        // add the source code to the shader and compile it        GLES20.glShaderSource(shader, shaderCode);        GLES20.glCompileShader(shader);        return shader;    }    public static void checkGlError(String glOperation) {        int error;        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {            Log.e(TAG, glOperation + ": glError " + error);            throw new RuntimeException(glOperation + ": glError " + error);        }    }}

如果坐标变换变为下面这样:

// Setup our screen width and height for normal sprite translation.        Matrix.orthoM(mProjectionMatrix, 0, 0f, width, 0.0f, height, 0, 50);        // Set the camera position (View matrix)        Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);        // Calculate the projection and view transformation        Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

则只需将vertices初始化的代码变为下面这样即可:

vertices = new float[364 * 3];        int x = 540,y=960,r=200;                for (int i =0; i <364; i++){            vertices[(i * 3)+ 0] = (float) (Math.cos((3.14/180) * (float)i )) * r +x;            vertices[(i * 3)+ 1] = (float) (Math.sin((3.14/180) * (float)i )) * r + y;            vertices[(i * 3)+ 2] = 0;        }

如果要画空心圆,只需将

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);

变为:

GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, vertexCount);//空心

即可。

更多相关文章

  1. [置顶] Android百度地图SDK 导航SDK2.0结合定位SDK6.0.5的导航参
  2. Android-Opengl 实现图片滤镜功能
  3. DDMS
  4. view中显示部分区域
  5. Android(安卓)点击View Rotate旋转带视图动画
  6. Android(安卓)图片与屏幕坐标点
  7. android 自动化测试之MonkeyRunner学习(二)
  8. android 线段与矩形碰撞检测
  9. android图片的打开和缩放时出现oom处理过程

随机推荐

  1. android 标题栏下拉选择控件(下拉菜单宽度
  2. Unity3d报错:Error building Player: Win3
  3. android 主界面 底部菜单 DEMO
  4. 学ios还是学android
  5. Android Support Library的前世今生
  6. android的问题
  7. 关于Android RenderScript 的详细说明和
  8. Android支持Java哪些特性?
  9. Android 4权威专家撰写,经典作品最新升级
  10. Android中的事件处理机制