从openGL中的顶点缓冲区读取位置数据

时间:2016-05-31 18:19:07

标签: ios opengl-es opengl-es-2.0

假设我们有一个对象,我们想要创建多个对象并根据某些算法独立移动它们。 以下是我正在使用的流程:

  1. 使用对象的几何图形创建结构
  2. 使用对象的几何体
  3. 创建顶点缓冲区数组
  4. 现在在渲染例程中,我需要遍历每个对象并根据特定算法改变它们的位置。
  5. 要完成此操作,我需要获取对象的当前位置以计算新位置。
  6. 如何获取顶点缓冲区的当前位置?显然,我不希望在程序外存储对象的所有位置,因为它们位于顶点缓冲区内。

    编辑:这是我用来存储和检索每个对象的模型矩阵中的数据的代码

    // Set up Code
    - (void)setupGL
    {
        [EAGLContext setCurrentContext:self.context];
        [self loadShaders];
        glEnable(GL_DEPTH_TEST);
        for( int i; i<num_objects; i++) {
            glGenVertexArraysOES(1, &_objectArray[i]);
            glBindVertexArrayOES(_objectArray[i]);
    
            glGenBuffers(1, &_objectBuffer[i]);
            glBindBuffer(GL_ARRAY_BUFFER, _objectBuffer[i]);
            glBufferData(GL_ARRAY_BUFFER, sizeof(objectData), objectData, GL_STATIC_DRAW);
    
            glEnableVertexAttribArray(....);
            glVertexAttribPointer(......, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
        }
        glBindVertexArrayOES(0);
    }
    //********************************************************
    // Rendering Code
    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    {
        glUseProgram(_program);
        for(int i=0; i<num_objects; i++) {
    
            glBindVertexArrayOES(_objectArray[i]);
    
            // Get Previous data
            GLint uMatrix = glGetUniformLocation(_program, "modelMatrix");
            glGetUniformfv(_program, uMatrix, dataOfCurrentObject);
    
           // Get Previous data
           ... transform dataOfCurrentObject based on an algorithm and create newDataOfCurrentObject
    
           // Update object with new data and draw
           glUniformMatrix4fv(uMatrix, 1, 0, newDataOfCurrentObject);
           glDrawArrays(GL_TRIANGLES, 0, 36);
        }
    }
    

    我现在遇到的问题是对象'i'的dataOfCurrentObject与对象'i-1'的newDataOfCurrentObject相同。换句话说,似乎代码仅跟踪所有对象的一个​​模型矩阵,或者它不能正确读取特定对象的模型矩阵。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

使用的最简单方法是在模型矩阵中设置对象的位置,并在每次绘制新对象时将该对象的相应模型矩阵上传为Uniform。 [伪]代码看起来像这样:

for(game_object object : game_object_list) {
    glUniformMatrix4f(modelMatrixUniformLocation, 1, false, object->model_matrix);
    object->draw();
}

当您需要更新对象的位置时:

for(game_object object : game_object_list) {
    object->model_matrix = Matrix.identity();
    /*Any transformations that need to take place here*/
    object->model_matrix = object->model_matrix.transpose(/*x*/, /*y*/);
    /*Any other transformations that need to take place*/
}

根据您的需要,您输入的具体内容会有所不同。如果您正在编写2D游戏,那么您可能不需要4x4模型矩阵。但基本逻辑应该与你最终使用的相同。

答案 1 :(得分:0)

您不必从顶点缓冲区读取任何内容。您只需要在应用程序中保留所需的转换,并将其作为每个对象的统一传递。

例如,如果您需要翻译对象,请保持modelViewMatrix并且每个帧都将trasformation应用于前一个矩阵:

GLKMatrix4 modelViewMatrix;
...
modelViewMatrix = GLKMatrix4Identity;
...
-(void) render {
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, deltaX, deltaY, deltaZ);
    glUniformMatrix4fv(_modelViewUniform, 1,0, modelViewMatrix.m);
}

所以你只需要继续引用你的对象modelView矩阵并相应地应用你的转换。

如果要将数据从顶点缓冲区(gpu)读回到应用程序,则必须使用变换反馈,这是一种更高级的技术,在您修改顶点时使用它顶点着色器,您需要返回结果。 (你的情况不需要)。