动态更改顶点缓冲区数据opengl

时间:2016-11-09 20:41:03

标签: android opengl-es opengl-es-2.0

我有一个点类,它使用缓冲区绘制一些点。我希望能够改变所绘制内容的内容(用新点更新场景)。重新创建一个全新的对象听起来并不好,所以我一直试图改变缓冲区的内容。最近我发现了glBufferSubData(),但我不知道如何使用它。

这是我的观点类:

public class Point {
    private  int mProgram, mPositionHandle, mColorHandle, mMVPMatrixHandle;
    private FloatBuffer vertexBuffer,colorBuffer;
    private static final int COORDS_PER_VERTEX = 3;
    private static final int COORDS_PER_COLOR = 3;
    private  int vertexCount,colorCount;


    private final String vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute mediump vec4 vColor;" +
                    "varying mediump vec4 vaColor;" +
                    "void main() {" +
                    "  vaColor = vColor;" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "   gl_PointSize = 20.0;" +
                    "}";

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


    private static int vertexStride = COORDS_PER_VERTEX * 4;
    private final int colorStride = COORDS_PER_COLOR * 4;


    public Point(float pointCoords[],float colorCoords[]){
        this.vertexCount = pointCoords.length / COORDS_PER_VERTEX;
        this.colorCount = colorCoords.length / COORDS_PER_COLOR;

        ByteBuffer vbb = ByteBuffer.allocateDirect(pointCoords.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        vertexBuffer = vbb.asFloatBuffer();
        vertexBuffer.put(pointCoords);
        vertexBuffer.position(0);



        ByteBuffer cbb = ByteBuffer.allocateDirect(colorCoords.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        colorBuffer = cbb.asFloatBuffer();
        colorBuffer.put(colorCoords);
        colorBuffer.position(0);


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

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();

        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);

        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);

        // creates OpenGL ES program executables
        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 point coordinate data
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);


        mColorHandle = GLES20.glGetAttribLocation(mProgram,"vColor");

        GLES20.glEnableVertexAttribArray(mColorHandle);
        // Set color for drawing the triangle
        GLES20.glVertexAttribPointer(mColorHandle, COORDS_PER_COLOR, GLES20.GL_FLOAT, false,
                colorStride, colorBuffer);

        // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

        //TRANSLATION
        float[] transMatrix = new float[16];

        Matrix.setIdentityM(transMatrix,0);
        Matrix.translateM(transMatrix,0,0.5f,0,0);
        Matrix.multiplyMM(transMatrix,0,mvpMatrix,0,transMatrix,0);


        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

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

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

    /**
     * Change content of buffer
     */
    public void changeBufferData(float[] newBufferInfo) {
        GLES20.glBufferSubData(?,0,newBufferInfo.length*4,vertexBuffer);
    }

    }

1 个答案:

答案 0 :(得分:0)

您目前正在使用客户端顶点数组,其中每个绘图使用glVertexAttribPointer上传数据。动态更新它不会比你现在做的更昂贵,因为你已经不得不为每次绘制操作分配和复制数据到驱动程序拥有的内存中。

但是,正如您所说,重新创建缓冲区是昂贵的,因此强烈建议避免客户端顶点上传...

您缺少的部分是需要创建顶点缓冲区对象(glGenBuffers等),然后您可以使用它而不是客户端属性。 glBufferDataglSubBufferData用于修补其中一个缓冲区对象的内容。