2

Im having problems to add a struct to a OpenGL VBO

This is my struct

struct Vertex {

    //vertices
    std::vector<glm::vec3> vertices;

    //texture coordinates
    std::vector<glm::vec3> texCord;
}

This is how im assigning and initializing the VBO

glGenVertexArrays(1, &buffer.VAO);
glGenBuffers(1, &buffer.VBO);
glGenBuffers(1, &buffer.EBO);

glBindBuffer(GL_ARRAY_BUFFER, buffer.VAO);

//Initialize buffer data 
glBindBuffer(GL_ARRAY_BUFFER, buffer.VBO);
glBufferData(GL_ARRAY_BUFFER,
            vertex.vertices.size() * sizeof(glm::vec3) +
            vertex.texCord.size() * sizeof(glm::vec3)
            &vertex,
            GL_STATIC_DRAW);

//indices attribute
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex.indices.size() * sizeof(glm::vec2), &vertex.indices[0], GL_STATIC_DRAW);

//vertices coordinates attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertices));

//texture coordinates attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCord));

And my draw command looks like this

glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(buffer.VAO);
glDrawElements(GL_TRIANGLES, vertex.indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

Is it possible to initialize buffer data with a raw struct and if yes how?

Denmuell
  • 87
  • 1
  • 10

2 Answers2

3

std::vector stores a pointer to dynamically allocated memory. However, you must pass a consecutive buffer to glBufferData.
Create the object's data store with glBufferData, but use glBufferSubData to initialize the buffer:

size_t vertexSize = vertex.vertices.size() * sizeof(glm::vec3);
size_t texCordSize = vertex.texCord.size() * sizeof(glm::vec3);

glBufferData(GL_ARRAY_BUFFER, vertexSize + texCordSize, nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexSize, vertex.vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertexSize, texCordSize, vertex.texCord.data());
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • When my draw command gets excuted, it is throwing the following exception `Exception thrown at 0x00007FF9B83BE740 (nvoglv64.dll) in HotEvo.exe: 0xC0000005: Access violation reading location 0x0000000000000000.`. My draw command looks like that `glDrawElements(GL_TRIANGLES, vertex.indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0);` Any Ideas what might be wrong now? – Denmuell Apr 13 '21 at 16:45
  • 1
    Is this a new question? For the use of `glDrawElements` you must specify an index buffer. If you don't have an index buffer, you have to use `glDrawArrays`. – Rabbid76 Apr 13 '21 at 16:47
  • I am specify it already, I just sniped it out for readabilty purpoeses but i added it now and also my drawing command into my question. Can you spot a Problem? Thanks for the help already with `glBufferSubData`! – Denmuell Apr 13 '21 at 17:02
  • 1
    @Denmuell Why is the size of the element buffer `vertex.indices.size() * sizeof(glm::vec2)`? The indices have to be integral. – Rabbid76 Apr 13 '21 at 17:09
  • Is the VAO already bound, when you bind the element buffer? See [Index buffers](https://www.khronos.org/opengl/wiki/Vertex_Specification#Index_buffers) – Rabbid76 Apr 13 '21 at 17:11
  • You spotted an error regarding the size of the element buffer. It now looks like this: `vertex.indices.size() * sizeof(unsigned int) `. But im still getting the same error message – Denmuell Apr 13 '21 at 17:22
  • Regarding the binding, i made a typo at `glBindVertexArray(scene[i].buffer.VBO);` I did correct it in the question now and changed VBO to VAO. – Denmuell Apr 13 '21 at 17:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231074/discussion-between-denmuell-and-rabbid76). – Denmuell Apr 13 '21 at 17:22
  • @Denmuell Do you call somewhere `glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);`. If so, remove it. – Rabbid76 Apr 13 '21 at 17:30
  • Nope im not calling it somewhere. Im just calling the EBO when I´m initializing the indices – Denmuell Apr 13 '21 at 17:33
  • Where do you call `glBufferData(GL_ARRAY_BUFFER, buffer.VBO);`? – Rabbid76 Apr 13 '21 at 17:34
  • I can just guess here. I can't debug your application with only seeing the code snippet in the question. I recommend reading [Khronos OpenGL wiki - Debug Output](https://www.khronos.org/opengl/wiki/Debug_Output). See also [GitHub - graphics-snippets - C++ code snippets - Debug context and Debug output](https://github.com/Rabbid76/graphics-snippets/blob/master/documentation/cpp_code_snippets.md#debug-context-and-debug-output) – Rabbid76 Apr 13 '21 at 17:35
  • Thanks for recommending that and also for helping me so far. I probably need to invest more time into the documenation of OpenGL. – Denmuell Apr 13 '21 at 17:40
  • If you are still intrested in finding the error tho then here is my like to the github repo https://github.com/0xdenmuell/HotEvo/tree/in_progress – Denmuell Apr 13 '21 at 17:41
1

Thanks to @Rabbid76 I now solved my problem. Code is down below.

Note: I need to create the buffer before filling data with glBufferSubData

glGenVertexArrays(1, &buffer.VAO);
glGenBuffers(1, &buffer.VBO);
glGenBuffers(1, &buffer.EBO);

glBindBuffer(GL_ARRAY_BUFFER, buffer.VAO);

int vertexSize = sizeof(glm::vec3) * vertex.vertices.size();
int texCordSize = sizeof(glm::vec2) * vertex.texCord.size();
int totalSize = vertexSize + texCordSize;

int indicesSize = sizeof(unsigned int) * vertex.indices.size();

//Create Buffer dynamically
glBufferData(GL_ARRAY_BUFFER, totalSize, NULL, GL_DYNAMIC_DRAW);

//Fill the buffer with data 
glBindBuffer(GL_ARRAY_BUFFER, buffer.VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexSize, vertex.vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertexSize, texCordSize, vertex.texCord.data());

//indices attribute
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, vertex.indices.data(), GL_STATIC_DRAW);

//position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) + sizeof(glm::vec2), (void*)0);
        
//texture attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec3) + sizeof(glm::vec2), (void*)sizeof(glm::vec3));

glBindVertexArray(0);
Denmuell
  • 87
  • 1
  • 10