Is there a way to share data between shaders?
Do i just create a VAO and then swich shader programs as needed?
I guess shaders probably need to have the same layout then.
Or do i create VBO-s and per object-shader pair i create the VAO that binds data to shader variables?
This should load most data only once to the OpenGl + i could reuse quite alot.
I tried the second approach, but im not sure if it has reduced memory usage or not. The code pieces in question are below, i hope its enough.
Or is there some other, even better way?
Idea is to reduce the memory usage, and general speedup of the process.
void Mesh::bind()
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, verticesCount * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, nbo);
glBufferData(GL_ARRAY_BUFFER, normalCount * sizeof(GLfloat), normals, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, uvbo);
glBufferData(GL_ARRAY_BUFFER, uvCount * sizeof(GLfloat), UVs, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * sizeof(GLuint), indices, GL_STATIC_DRAW);
}
void MeshRenderer::init()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBufferId());
GLuint posId = shaderProgram->getAttribute("LVertexPos2D");
glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(posId);
glBindBuffer(GL_ARRAY_BUFFER, mesh->getNormalBufferId());
GLuint normId = shaderProgram->getAttribute("LVertexNorm");
glVertexAttribPointer(normId, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(normId);
glBindBuffer(GL_ARRAY_BUFFER, mesh->getUVBufferId());
GLuint uvId = shaderProgram->getAttribute("uv");
glVertexAttribPointer(uvId, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(uvId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndexBufferId());
glBindVertexArray(0);
}
GameObject* GameObject::createCustom(Mesh* mesh)
{
Texture* texture = new Texture();
texture->loadFromFile("UV.png", NULL);
GenericShaderProgram* shader = new GenericShaderProgram("basic.vs", "basic.fs");
shader->loadProgram();
return new GameObject(texture, shader, mesh);
}
GameObject::GameObject(Texture* texture, ShaderProgram* program, Mesh* mesh)
{
this->texture = texture;
dir = new Vector3(1, 0, 0);
meshRenderer = new MeshRenderer(mesh, program);
transform.setRotation(1.57, 1, 0, 0);
transform.translate(Vector3(0, -2, 0));
transform.setScale(Vector3(1, 1, 1));
}
//In main.cpp
Mesh* mesh = new Mesh();
mesh->cubePrimitive();
mesh->init();
object = GameObject::createCustom(mesh);
object2 = GameObject::createCustom(mesh);
object3 = GameObject::createCustom(mesh);
Related
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?
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());
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);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm trying to display two shapes in OpenGL.
First I got the vertices,uvs, normals,indices from an obj file and texture form DDS and stored them in an array of struct Shape.
Then I indexed the vertices, uvs, normals and indices for all the shapes in 4 respective array, also storing the number of total number of vertices, uvs , normals and indices in another vector.
Then I initialized the VBOs.
Then I creates vertex array objects for the two shapes and set them up giving respective VertexAttribPointer. (I think the problem is in this step)
Finally I bind the respective VAOs and display them but only one shape is being displayed.
Where exactly am I going wrong.
Code for VBOindexing :
std::vector<glm::vec4> elecount;
long long int endind = 0,endver=0,enduv=0,endnr=0;
std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
for (int i = 0;i < componentcount ;i++)
{
endver = endind = enduv = endnr = 0;
indexVBO(component[i].vertices, component[i].uvs, component[i].normals, indices, indexed_vertices, indexed_uvs, indexed_normals);
endind = indices.size();
endver = indexed_vertices.size();
enduv = indexed_uvs.size();
endnr = indexed_normals.size();
elecount.push_back(glm::vec4(endver, enduv, endnr, endind));
}
Code for VBOs :
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW);
GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
Code for VAOs :
GLuint CubeVertexArrayID, SphereVertexArrayID;
glGenVertexArrays(1, &CubeVertexArrayID);
glGenVertexArrays(1, &SphereVertexArrayID);
glBindVertexArray(CubeVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBindVertexArray(SphereVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(glm::vec3) * ((int)elecount[0][0])));
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec2) * ((int)elecount[0][1])));
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * ((int)elecount[0][2])));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
Code for displaying :
glBindVertexArray(CubeVertexArrayID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, component[0].Texture);
glUniform1i(TextureID, 0);
glDrawElements(GL_TRIANGLES,(int)elecount[0][3],GL_UNSIGNED_SHORT,(void*)0);
glm::mat4 ModelMatrix2 = glm::mat4(1.0);
ModelMatrix2 = glm::translate(ModelMatrix2, glm::vec3(2.0f, 0.0f, 0.0f));
glm::mat4 MVP2 = ProjectionMatrix * ViewMatrix * ModelMatrix2;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP2[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix2[0][0]);
glUseProgram(shaderProg);
glBindVertexArray(SphereVertexArrayID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, component[1].Texture);
glUniform1i(TextureID, 0);
glDrawElements(GL_TRIANGLES, (int)(elecount[1][3]-elecount[0][3]), GL_UNSIGNED_SHORT,(void*)(sizeof(unsigned short) * ((int)elecount[0][3])));
There's nothing wrong in the code you posted, so it's hard to say for sure where's the problem. However my best guess is that indexVBO (that you didn't show) pushes the absolute indices within indexed_* arrays. Combined with the offset glVertexAttribPointer of SphereVertexArrayID this causes out-of-bound reads.
You could fix your indexVBO code. However, since both VAOs reference the same buffer, the simplest solution (and I would say, the correct solution) is to use a single VAO for both components. If my hypothesis is correct, it is as simple as changing the
glBindVertexArray(SphereVertexArrayID);
to
glBindVertexArray(CubeVertexArrayID);
when you're drawing the 2nd component. Then you can get rid of SphereVertexArrayID completely.
I am attempting to create a simple graphics system using modern (3.3) OpenGL for use in a game. Dynamic objects will have dynamic geometry and VBOs will be updated whenever there is a change. This part was very easy to implement. While everything works well so long as only one VAO is used, further calls to glGenVertexArrays don't create another object (printing the ID for the first and the second both returns 1) and something in the VAO initialization for the new objects renders the first one unable to perform any edits. Every "modern OpenGL" tutorial either only uses one object or has some pretty significant conflicts (most often the use of glVertexAttribPointer). The following code is involved with the graphics system of the objects. (Don't know how important this is, but I am using glfw3 for window and and context creation).
Init Game Object (graphics snippet)
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
glGenBuffers(1, &vertexCoordBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexCoordBufferID);
glBufferData(GL_ARRAY_BUFFER, 2000 * 3 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
allocatedVerticies = 2000;
Update Mesh
//generate mesh
std::vector<float> vertices;
vertices.reserve(voxels.size() * 3 * 12);
//Vertices are added to the vector. This part works. Removed this code for clarity.
vertexCount = vertices.size() / 3;
glBindVertexArray(vertexArrayID);
glBindBuffer(GL_ARRAY_BUFFER, vertexCoordBufferID);
if (allocatedVerticies < vertexCount)
{
//reallocate the buffers
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
allocatedVerticies = vertexCount;
}
else
{
/////////////////////////////
//reallocate the buffers- originally a reallocation was not going to be used, but glBufferSubData does not work
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
allocatedVerticies = vertexCount;
////////////////////////////////////////this does not work for some reason
//reset data
//glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data());
}
edited = false;
Render Object
glBindVertexArray(vertexArrayID);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
If anyone more experienced with OpenGL could point out my mistake, (or some other problem) that would be fantastic.
In code that you provided I see nothing that can cause such a behaviour. Maby you should provide your entire solution that is connected with your rendering for better understanding what is going on in your program?
By the way: if you already defined glVertexAttribPointer() for your buffor you don't have to do it every time you update the data you stored in your vertexCoordBufferID if of course you don't change the data layout and its type. Instead of:
vertexCount = vertices.size() / 3;
glBindVertexArray(vertexArrayID);
glBindBuffer(GL_ARRAY_BUFFER, vertexCoordBufferID);
if (allocatedVerticies < vertexCount)
{
//reallocate the buffers
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
allocatedVerticies = vertexCount;
}
You can use just:
vertexCount = vertices.size() / 3;
glBindBuffer(GL_ARRAY_BUFFER, vertexCoordBufferID);
if (allocatedVerticies < vertexCount)
{
//reallocate the buffers
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
allocatedVerticies = vertexCount;
}
Whenever I try to draw a mesh using glDrawElements, my program gets no errors, but it doesn't draw anything. I'm pretty sure that the issue is with glDrawElements since if I comment glDrawElements out and replace it with glDrawArrays, it works perfectly. So, my question is, can anyone help me figure out why this is happening?
Also glGetError returns no errors
#include "Mesh.h"
Mesh::Mesh(glm::vec2* vertices, glm::vec2* texCoords, GLushort* elements, int size)
{
m_size = size;
m_vertices = vertices;
m_elements = elements;
movementVector = glm::vec2(0.0f, 0.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), vertices, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glGenBuffers(1, &tex_vbo);
glBindBuffer(GL_ARRAY_BUFFER, tex_vbo);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(float), texCoords, GL_STATIC_DRAW);
// note: I assume that vertex positions are location 0
int dimensions = 2; // 2d data for texture coords
glVertexAttribPointer(1, dimensions, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (1); // don't forget this!
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &vbo);
}
void Mesh::Draw()
{
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
//glDrawArrays(GL_TRIANGLES, 0, 8);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);
glDisableVertexAttribArray(0);
}
Here's a link to the code handling drawing objects to the screen, also, I have tested my shaders, they are fully functional and unless drawing via glDrawElements requires changes to the shaders as well, then there is nothing that is causing this with them.
The problem I am having is that once I create a VBO for the main geometry in a level, when I create a second for the objects, the object VBO does not work. I am assuming I have some buffer bound incorrectly but I can't for the life of me find it. I create the level VBO first and then the object VBO and again, when I disable the creation of the level VBO, the object VBO creates correctly.
Here is my code.
in level.h:
// Zone VBO
GLuint zoneVBO;
GLuint zoneVAO;
GLuint zoneIBO;
// Object VBO
GLuint objVBO;
GLuint objVAO;
GLuint objIBO;
Creation of zone (geometry) VBO - just as a note, the creation works correctly in both VBOs so the data moving around isn't the issue, it is I think, a binding error:
void WLD::createZoneVBO()
{
// Get the size for our VBO
int numVert = 0;
int numPoly = 0;
int VBOsize = 0;
int IBOsize = 0;
// Get the count of vertices and polygons
for(int i = 0; i < zoneFragMap[0x36]; i++)
{
numVert += zmeshes[i].numVert;
numPoly += zmeshes[i].numPoly;
VBOsize += zmeshes[i].numVert * sizeof(Vertex);
IBOsize += zmeshes[i].numPoly * 3 * sizeof(GLuint);
}
// Create the IBO and VBO data
GLuint* iboData = new GLuint[zonePolyProcessed * 3];
Vertex* vboData = new Vertex[zoneVertProcessed];
int iboPos = 0;
int vboPos = 0;
// Create the VBO and IBO
for(int i = 0; i < zoneFragMap[0x36]; i++)
{
// Copy the data to the IBO
memcpy(&iboData[iboPos], zmeshes[i].indices, zmeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));
// Advance the position
iboPos += zmeshes[i].numPoly * 3;
// Copy the data to the VBO
memcpy(&vboData[vboPos], zmeshes[i].vertices, zmeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));
// Advance the position
vboPos += zmeshes[i].numVert;
}
//Create VBO for the triangle
glGenBuffers(1, &zoneVBO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
glBufferData(GL_ARRAY_BUFFER, zoneVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Create the IBO for the triangle
//16 bit indices
//We could have actually made one big IBO for both the quad and triangle.
glGenBuffers(1, &zoneIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, zonePolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(0);
delete[] iboData;
delete[] vboData;
}
And the objects - again, the object geometry is loaded perfectly, but only if the zone geometry hasn't been loaded yet:
void WLD::createObjectVBO()
{
// Get the size for our VBO
int numVert = 0;
int numPoly = 0;
int VBOsize = 0;
int IBOsize = 0;
// Get the count of vertices and polygons
for(int i = 0; i < objFragMap[0x36]; i++)
{
numVert += objMeshes[i].numVert;
numPoly += objMeshes[i].numPoly;
VBOsize += objMeshes[i].numVert * sizeof(Vertex);
IBOsize += objMeshes[i].numPoly * 3 * sizeof(GLuint);
}
// Create the IBO and VBO data
GLuint* iboData = new GLuint[objPolyProcessed * 3];
Vertex* vboData = new Vertex[objVertProcessed];
int iboPos = 0;
int vboPos = 0;
// Create the VBO and IBO
for(int i = 0; i < objFragMap[0x36]; i++)
{
// Copy the data to the IBO
memcpy(&iboData[iboPos], objMeshes[i].indices, objMeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));
// Advance the position
iboPos += objMeshes[i].numPoly * 3;
// Copy the data to the VBO
memcpy(&vboData[vboPos], objMeshes[i].vertices, objMeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));
// Advance the position
vboPos += objMeshes[i].numVert;
}
//Create VBO for the triangle
glGenBuffers(1, &objVBO);
glBindBuffer(GL_ARRAY_BUFFER, objVBO);
glBufferData(GL_ARRAY_BUFFER, objVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Create the IBO for the triangle
//16 bit indices
//We could have actually made one big IBO for both the quad and triangle.
glGenBuffers(1, &objIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, objPolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Create the VAO
glGenVertexArraysAPPLE(1, &objVAO);
glBindVertexArrayAPPLE(objVAO);
glBindBuffer(GL_ARRAY_BUFFER, objVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(0);
}
Rendering these two VBOs:
opaque.Use();
glBindVertexArrayAPPLE(getVAO(2));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
renderGeometry(&cameraMat, 0, curRegion);
glBindVertexArrayAPPLE(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayAPPLE(objVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
glBindBuffer(GL_ARRAY_BUFFER, objVBO);
glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
renderObjects(&cameraMat);
glBindVertexArrayAPPLE(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
opaque.UnUse();
To summarize, I think it's an issue in the creation of the VBOs. I think I am doing something wrong and keeping something bound when it should be bound.
// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO); //<-------
glEnableVertexAttribArray(0);
In the line I have highlighted, this looks like it should be zoneVBO, not zoneVAO.
You should be checking for errors with glGetError, it might have spotted this mistake.
Also it's not required to bind the buffers before calling renderObjects. If you have the vertex pointer stored in the VAO, then you do not need to bind the buffer, as the vertex pointers already point to the correct location.