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);
    }

}

因爲屏幕寬高比的原因目前繪製出來的本身就是橢圓形,後面會再繼續探索矩陣變換相關,實現真的圓形

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