OpenGL ES:一个VBO - 几个精灵 - 分别翻译每个个体

问题描述:

我想知道当这些精灵的顶点存储在同一个VBO中时,如何个别访问和操作每个精灵。出于性能的原因,我使用纹理图来表示我的精灵,然后将它们映射到顶点阵列。我尝试了将不同的顶点数组中的精灵分开,并将它们放在不同的VBO中。但是,如果我画出100个精灵,那么这个效果会很好,因为每次打电话都需要进行很多单独的抽签。相反,我想使用同一个VBO,并从中分别转换每个精灵。这可能吗?OpenGL ES:一个VBO - 几个精灵 - 分别翻译每个个体

源代码

 @Override 
public void onSurfaceCreated(GL10 unused, EGLConfig config) { 

    vertexBuffer = GLData.createVertices(nSprites, vertices); 
    GLData.createUvsData(nSprites, alienUvs, uvBufferAlien); 
    //drawListBuffer = GLData.createIndices(indices, nSprites); 
    GLData.createVertexBufferObject(vertexBuffer,nSprites, uvBufferAlien, bufferId.length, bufferId); 

    createCamera(); 

    GLES20.glEnable(GLES20.GL_CULL_FACE); 

    GLES20.glEnable(GLES20.GL_BLEND); 
    GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); 

    // get shadersource 
    final String vertexShader = getVertexShader(); 
    final String fragmentShader = getFragmentShader(); 

    final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader); 
    final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader); 

    mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, 
      new String[] {"a_Position", "a_Color", "a_Normal", "a_TexCoordinate"}); 

    //create texture 
    textureHandle = TextureHelper.loadTexture(context); 

    GLES20.glUseProgram(mProgramHandle); 

    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix"); 
    mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix"); 
    //mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color"); 
    mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate"); 

    mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position"); 

} 

@Override 
public void onSurfaceChanged(GL10 unused, int width, int height) { 

    game_width = width; 
    game_height = height; 

    GLES20.glViewport(0, 0, width, height); 


    // Create a new perspective projection matrix. The height will stay the same 
    // while the width will vary as per aspect ratio. 
    final float ratio = (float) width/height; 
    final float left = -ratio; 
    final float right = ratio; 
    final float bottom = -1.0f; 
    final float top = 1.0f; 
    final float near = 1f; 
    final float far = 20.0f; 

    Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); 

} 


@Override 
public void onDrawFrame(GL10 unused) { 

    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, 2, 0f, -7f); 

    draw(); 

} 

private void draw() { 

    //uvs 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId[0]); 
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, 0); 


    //vertices 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId[1]); 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, 0); 


    // Clear the currently bound buffer (so future OpenGL calls do not use this buffer). 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 



         /* MATRIX */ 

    // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix 
    // (which currently contains model * view). 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 

    // Pass in the modelview matrix. 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 

    // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix 
    // (which now contains model * view * projection). 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 

    // Pass in the combined matrix. 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

    // Draw the sprites 

    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * nSprites); 

} 

顶点着色器

attribute vec4 a_Position; 
uniform mat4 u_MVMatrix; 
uniform mat4 u_MVPMatrix; 
void main()  { 

    gl_Position = u_MVPMatrix * a_Position; 

} 

您可以上传一个统一的矩阵阵列和索引,作为每个顶点属性为每个精灵给你一个独特的矩阵对于每个精灵(用于蒙皮骨骼动画模型的技术,但也适用于此)。

但是,对于简单的精灵来说,上传矩阵的成本几乎与更新位置数组一样昂贵,并且您需要担心的统一数组大小的限制。您可能会更好,只需在软件中对它们进行动画制作,并为每批中的每个顶点上传一个新位置。将位置分割成单独的缓冲区,例如您的纹理坐标,以最大限度地减少您上传每个帧的带宽。

+0

谢谢我会看看这个:-) – java

+0

我做了一个好的答案 - 但问题没有解决。事实上 - 无法相信 - 当我在Galaxy S3上使用我的应用程序(从S7切换)时,帧时间下降到了20点。我一直在想这个问题,但它可能是1920×1856的textureatlas ?要么因为它的非POT或它太大?我会试试这个 - 如果它不起作用,我会在堆栈上提出一个新问题并给你链接。谢谢!!!!!!! – java

+0

您是否修改纹理图集或现有缓冲区而不进行流水线操作?你可能会触发大量的资源拷贝。 查看https://community.arm.com/graphics/b/blog/posts/mali-performance-6-efficiently-updating-dynamic-resources – solidpixel