OpenGL ES2.0 绘制圆形

Opengles 绘制的方式 

int GL_POINTS //将传入的顶点座标作为单独的点绘制
int GL_LINES //将传入的座标作为单独线条绘制,ABCDEFG六个顶点,绘制AB、CD、EF三条线
int GL_LINE_STRIP //将传入的顶点作为折线绘制,ABCD四个顶点,绘制AB、BC、CD三条线
int GL_LINE_LOOP //将传入的顶点作为闭合折线绘制,ABCD四个顶点,绘制AB、BC、CD、DA四条线。
int GL_TRIANGLES //将传入的顶点作为单独的三角形绘制,ABCDEF绘制ABC,DEF两个三角形
int GL_TRIANGLE_FAN //将传入的顶点作为扇面绘制,ABCDEF绘制ABC、ACD、ADE、AEF四个三角形
int GL_TRIANGLE_STRIP //将传入的顶点作为三角条带绘制,ABCDEF绘制ABC,BCD,CDE,DEF四个三角形

opengles不能直接绘制圆形,而是通过将圆形分割成无限个三角形,这样看起来就像是圆形了。

说明:画了三角形、矩形、圆形基本可以确定,opengles 提供了两个绘制接口

1.指定绘制模式(自带绘制顺序) 顶点绘制

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

2.自定义绘制顺序 索引绘制

GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

这两种都离不开:顶点座标,绘制顺序 这两个必备要素

 

圆形绘制直接使用 GLES20.GL_TRIANGLE_FAN 这种自带的方式就可以了,或者自己写方法实现这种绘制顺序采用索引绘制也是一样的,n越大越像圆形,绘制椭圆也类似,将半径R分开成两个来计算座标就好了

 

public class Circle {

    private static final String TAG = Circle.class.getSimpleName();
    private FloatBuffer vertexBuffer;

    //顶点的个数
    private int vertexCount;

    //将圆形划分成n等份
    //每个顶点的座标个数
    private final int COORDS_PER_VERTEX = 3;

    private int vertexStride = COORDS_PER_VERTEX * 4;


    //绘制形状需要一个顶点着色程序和一个片段着色程序
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private float radius;
    private int count;

    private float x;
    private float y;
    private float z;

    private int program;

    public Circle(float radius, int count, float x, float y, float z) {
        this.radius = radius;
        this.count = count;
        this.x = x;
        this.y = y;
        this.z = z;

        ByteBuffer bb = ByteBuffer.allocateDirect((count + 2) * COORDS_PER_VERTEX * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        float[] coords = circleCoords();
        Log.i(TAG, "Circle: " + Arrays.toString(coords));

        vertexBuffer.put(coords);
        vertexBuffer.position(0);

        int vertexShader = GlRender_1.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = GlRender_1.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        program = GLES20.glCreateProgram();

        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);

        GLES20.glLinkProgram(program);

    }

    /*
     *将360°平均分成n 等份,求每个点的座标
     * */
    private float[] circleCoords() {
        //将圆形切成n块有n+1个顶点+圆心
        vertexCount = count + 2;
        float[] coords = new float[vertexCount * COORDS_PER_VERTEX];
        int offset = 0;
        coords[offset++] = x;
        coords[offset++] = y;
        coords[offset++] = z;
        for (int i = 0; i < count + 1; i++) {
            float angleInRadians = ((float) i / (float) count)
                    * ((float) Math.PI * 2f);
            coords[offset++] = x + radius * (float) Math.sin(angleInRadians);
            coords[offset++] = y + radius * (float) Math.cos(angleInRadians);
            coords[offset++] = z;
        }
        return coords;
    }

    private int positionHandle;
    private int colorHandle;
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

    public void draw() {
        GLES20.glUseProgram(program);

        positionHandle = GLES20.glGetAttribLocation(program, "vPosition");
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
        colorHandle = GLES20.glGetUniformLocation(program, "vColor");
        GLES20.glUniform4fv(colorHandle, 1, color, 0);

        //前三个点绘制一个三角形  后面是以(0,2,3)(0,3,4)(0,4,5)....
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount);

        GLES20.glDisableVertexAttribArray(positionHandle);
    }

}

因为屏幕宽高比的原因目前绘制出来的本身就是椭圆形,后面会再继续探索矩阵变换相关,实现真的圆形

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章