【问题标题】:Read position data from Vertex Buffer in openGL从openGL中的顶点缓冲区读取位置数据
【发布时间】:2016-06-02 01:00:52
【问题描述】:

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

  1. 使用对象的几何形状创建结构
  2. 使用对象的几何形状创建一个顶点缓冲区数组
  3. 现在在渲染例程中,我需要遍历这些对象中的每一个,并根据特定算法更改它们的位置。
  4. 为此,我需要获取对象的当前位置来计算新位置。

如何获取顶点缓冲区的当前位置?显然,我不想将对象的所有位置都存储在程序之外,因为它们都在顶点缓冲区内。

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

// 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 相同。换句话说,代码似乎只跟踪所有对象的一个​​模型矩阵,或者它没有正确读取特定对象的模型矩阵。有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

    最简单的方法是在模型矩阵中设置对象的位置,并在每次绘制新对象时将该对象的相应模型矩阵作为统一上传。 [伪]代码如下所示:

    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 模型矩阵。但是基本逻辑应该和你最终使用的一样。

    【讨论】:

    • 我已经尝试过这种方法,但我是在 iOS 应用程序上这样做的,所以 Matrix.identity() 不存在。你知道iOS中什么调用会得到模型矩阵吗
    • @Z.Zepos 我说这是伪代码。您需要查看您正在使用的 API(其中之一应该是数学/矩阵库)并查看您如何使用该库设置和重置矩阵。
    【解决方案2】:

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

    例如,如果您需要平移对象,请将 modelViewMatrix 保留在其中,并且每一帧都将转换应用于前一个矩阵:

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

    所以你只需要保持对你的对象模型视图矩阵的引用并相应地应用你的转换。

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

    【讨论】:

    • 如果我有数百万这样的对象,我将不得不将数百万这样的矩阵保存在程序内存中。显得相当浪费。从 GPU 取回数据有那么难吗?我错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2016-01-26
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多