Opengl 如何在使用实例数组时最小化GLVERTEXAttributePointer调用?

Opengl 如何在使用实例数组时最小化GLVERTEXAttributePointer调用?,opengl,vertex-buffer,vertex-array-object,Opengl,Vertex Buffer,Vertex Array Object,我有OpenGL代码,使用一个VAO处理所有模型数据和两个VBO。第一个用于位置和法线等标准顶点属性,第二个用于模型矩阵。我使用的是实例化绘制,因此我将模型矩阵作为实例化数组加载(基本上是顶点属性) 首先,我将标准顶点属性加载到VBO,并使用glvertexattributepointer设置所有内容一次。然后我将模型矩阵加载到另一个VBO。现在我必须在draw循环中调用glvertexattributepointer。我能不能阻止这一切 代码如下所示: // vertex data of al

我有OpenGL代码,使用一个VAO处理所有模型数据和两个VBO。第一个用于位置和法线等标准顶点属性,第二个用于模型矩阵。我使用的是实例化绘制,因此我将模型矩阵作为实例化数组加载(基本上是顶点属性)

首先,我将标准顶点属性加载到VBO,并使用
glvertexattributepointer
设置所有内容一次。然后我将模型矩阵加载到另一个VBO。现在我必须在draw循环中调用
glvertexattributepointer
。我能不能阻止这一切

代码如下所示:

// vertex data of all models in one array
GLfloat myvertexdata[myvertexdatasize];

// matrix data of all models in one array
// (one model can have multiple matrices)
GLfloat mymatrixdata[mymatrixsize];

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, myvertexdatasize*sizeof(GLfloat), myvertexdata, GL_STATIC_DRAW);

glVertexAttribPointer(
          glGetAttribLocation(myprogram, "position"),
          3,
          GL_FLOAT,
          GL_FALSE,
          24,
          (GLvoid*)0
);
glEnableVertexAttribArray(glGetAttribLocation(myprogram, "position"));
glVertexAttribPointer(
          glGetAttribLocation(myprogram, "normal"),
          3,
          GL_FLOAT,
          GL_FALSE,
          24,
          (GLvoid*)12
);
glEnableVertexAttribArray(glGetAttribLocation(myprogram, "normal"));

GLuint matrixbuffer;
glGenBuffers(1, &matrixbuffer);
glBindBuffer(GL_ARRAY_BUFFER, matrixbuffer);
glBufferData(GL_ARRAY_BUFFER, mymatrixsize*sizeof(GLfloat), mymatrixdata, GL_STATIC_DRAW);

glUseProgram(myprogram);


draw loop:
    int vertices_offset = 0;
    int matrices_offset = 0;
    for each model i:
        GLuint loc = glGetAttribLocation(myprogram, "model_matrix_column_1");
        GLsizei matrixbytes = 4*4*sizeof(GLfloat);
        GLsizei columnbytes = 4*sizeof(GLfloat);
        glVertexAttribPointer(
              loc, 
              4, 
              GL_FLOAT, 
              GL_FALSE, 
              matrixbytes,
              (GLvoid*) (matrices_offset*matrixbytes + 0*columnbytes)
        );
        glEnableVertexAttribArray(loc);
        glVertexAttribDivisor(loc, 1); // matrices are in instanced array
        // do this for the other 3 columns too...

        glDrawArraysInstanced(GL_TRIANGLES, vertices_offset, models[i]->num_vertices(), models[i]->num_instances());

        vertices_offset += models[i]->num_vertices();
        matrices_offset += models[i]->num_matrices();
我想到了在一个VBO中存储顶点数据和矩阵的方法。问题是如何正确设置步幅。我想不出一个解决办法

任何帮助都将不胜感激。

如果您有权访问(需要GL 4.2或),那么您可以这样做。将实例化属性内容与非实例化属性内容放在设置中:

GLuint loc = glGetAttribLocation(myprogram, "model_matrix_column_1");

for(int count = 0; count < 4; ++count, ++loc)
{
    GLsizei matrixbytes = 4*4*sizeof(GLfloat);
    GLsizei columnbytes = 4*sizeof(GLfloat);
    glVertexAttribPointer(
          loc, 
          4, 
          GL_FLOAT, 
          GL_FALSE, 
          matrixbytes,
          (GLvoid*) (count*columnbytes)
    );
    glEnableVertexAttribArray(loc);
    glVertexAttribDivisor(loc, 1); // matrices are in instanced array
}
即使在GL4.x之前的硬件上(只要它有最新的驱动程序),此功能也是可用的


但是,如果没有基本实例渲染,您将无能为力。您必须为要渲染的每个新实例集调整实例指针。这就是基本实例呈现存在的原因。

位置是否总是后续数字?@mak:您没有发布所有代码,因此我假设您的矩阵属性实际上是
mat4
,这是完全可以接受的。如果是,则选择4个位置。尽管如此,您根本不应该获取这些位置。您应该直接在着色器中指定它们。如果只执行一次,则获取位置会有什么问题?
glDrawArraysInstancedBaseInstance​(GL_TRIANGLES, vertices_offset, models[i]->num_vertices(), models[i]->num_instances(), matrix_offset);