2

我正在使用顶点缓冲区和元素缓冲区。

以下函数将顶点和元素数据作为数组并从中创建缓冲区。我的实际实现更复杂,当然会存储 id 以供以后使用,但这与这个问题无关。

void Create(const float Vertices[], const int Elements[])
{
    GLuint VertexBuffer, ElementBuffer; // ids

    glGenBuffers(1, VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, ElementBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Elements), Elements, GL_STATIC_DRAW);
}

在另一个函数中,我调用Create()传递两个表示立方体的数组。但什么也没有发生。窗口打开,我看到矢车菊蓝色背景没有任何立方体。

float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

Create(VERTICES, ELEMENTS);

如果我在函数内移动顶点和元素数据Create(),一切正常并且立方体被正确渲染。

void Create()
{
    GLuint VertexBuffer, ElementBuffer;

    float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
    int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

    glGenBuffers(1, VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW);

    glGenBuffers(1, ElementBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ELEMENTS), ELEMENTS, GL_STATIC_DRAW);
}

因此,我假设将数组传递给Create()函数时会出现问题。我没有收到任何编译器错误或警告。这里有什么问题?

4

2 回答 2

4

type 的参数const float Vertices[]实际上与const float Vertices*. 所以sizeof只是返回一个指针的大小。

使用模板来引用数组:

template<std::size_t VerticesN, std::size_t ElementsN>
void Create(const float (&Vertices)[VerticesN], const int (&Elements)[ElementsN])
{
// ...
}

// Usage is the same since template argument deduction

float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

Create(VERTICES, ELEMENTS);
于 2012-12-19T10:16:32.860 回答
3

The problem here is sizeof(VERTICES) and sizeof(ELEMENTS). When used in the Create() method the sizes of the arrays are known, but when you pass the arrays as a parameter (like in the Create(const float Vertices[], const int Elements[]) the array degrades to a pointer, and the sizeof is reduced to returning the size of the pointer.

One simple solution is to pass the size along with the arrays. So the function will look like this:

void Create(const float Vertices[], size_t VertSize, const int Elements[], size_t ElemSize) {
  ...
}

but I think I would prefer a solution that uses the new std::array which has a size() function:

void Create(const std::array<float>& vertices, std::array<int>& elements) {
  ...
}

If you do not have the opportunity to work with c++ 11, the boost libraries will provide the boost::array which mirrors the behaviour of c++ 11.

于 2012-12-19T10:17:32.320 回答