I am working on a school laboration whereas my task is to render a basic terrain using a heightmap, and also some sort of particle system (right now I'm just blasting away points that are drawn into flat squares).
The problem is that while I can render both the terrain and the particle system, for some reason I cannot render both of them at the same time.
The terrain's initiation and draw functions:
int Buffers()
{
ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "Vertex.txt"},
{ GL_FRAGMENT_SHADER, "Fragment.txt"},
{ GL_NONE, NULL},
};
program = LoadShaders(shaders);
createTerrain.loadBMP_custom("heightmap.bmp");
textureID = createTerrain.loadBMP_texture("texture.bmp");
textureLocID = glGetUniformLocation(program, "tex");
glUniform1i(textureLocID, textureID);
glGenBuffers(1, &VBOid); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, VBOid); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData)*createTerrain.vertices.size(), &createTerrain.vertices[0], GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glGenBuffers(1, &indexes);// bind kopplingarna med buffern
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexes);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*createTerrain.indices.size(), &createTerrain.indices[0], GL_STATIC_DRAW);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, createTerrain.globalWidth, createTerrain.globalHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, createTerrain.globalData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
MVPMatrixID = glGetUniformLocation(program, "gMVPMatrix");
return 0;
}
void Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glClearColor(1, 0, 0, 1);
glEnable(GL_DEPTH_TEST);
camera.SetPosition(glm::vec3(camera.ReturnPosition().x, height - createTerrain.checkHeight(camera.ReturnPosition().x, camera.ReturnPosition().z), camera.ReturnPosition().z));
camera.ComputeMatricesFromInputs(window);
projectionMatrix = camera.ReturnProjectionMatrix();
viewMatrix = camera.ReturnViewMatrix();
MVPMatrix = projectionMatrix * viewMatrix;
particles.CalculateMVPMatrix(camera);
//binda ihop location i shadern med buffern
glBindBuffer(GL_ARRAY_BUFFER, VBOid);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), BUFFER_OFFSET(16)); //The starting point of normals, 12 bytes away
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), BUFFER_OFFSET(28));
glUseProgram(program);
glUniformMatrix4fv(MVPMatrixID, 1, GL_FALSE, &MVPMatrix[0][0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexes);
glDrawElements(GL_TRIANGLES, createTerrain.indices.size(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
The particle systems init and draw functions:
void Particles::Init()
{
ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "ParticleVert.txt"},
{ GL_GEOMETRY_SHADER, "ParticleGeo.txt"},
{ GL_FRAGMENT_SHADER, "ParticleFrag.txt"},
{ GL_NONE, NULL},
};
program = LoadShaders(shaders);
glGenVertexArrays(1, VAOid);
glBindVertexArray(VAOid[0]);
glGenBuffers(1, &VBOid);
glBindBuffer(GL_ARRAY_BUFFER, VBOid);
glBufferData(GL_ARRAY_BUFFER, sizeof(PARTICLE) * particlePos.size(), &particlePos[0], GL_STATIC_DRAW);
MVPMatrixID = glGetUniformLocation(program, "gMVPMatrix");
}
void Particles::Render(glm::mat4 MVPMatrix)
{
UpdateParticles();
glBindBuffer(GL_ARRAY_BUFFER, VBOid);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glUseProgram(program);
glUniformMatrix4fv(MVPMatrixID, 1, GL_FALSE, &MVPMatrix[0][0]);
glDrawArrays(GL_POINTS, 0, maxParticles);
glDisableVertexAttribArray(0);
}
My current call order is Terrain.Buffers(), Particles.Init(), Terrain.Render(), Particles.Render().
As it looks now, the program will render the terrain and Only the terrain. What makes this such a troubling case is that there are two lines of code in Terrain.Render(), namely:
glUseProgram(program);
glUniformMatrix4fv(MVPMatrixID, 1, GL_FALSE, &MVPMatrix[0][0]);
If I switch place on these two, so that glUniformMatrix4fv comes before glUseProgram, the particles are rendered instead of the terrain.
EDIT:
added glGenVertexArrays(1, VAOid);
glBindVertexArray(VAOid[0]);
in the code, in Particles.Init. I honestly do not know how VAO's works, a friend of mine said this was all I needed to do. Hasn't solved the problem though.