Rendering a model in openGL - c++

I'm trying to render this model in openGL:
model in image viewer
this is my attempt so far:
model rendered by my code
I only gave it the verticies so far, no normals or faces. I'm wondering why it doesn't look full like the first one. Is it because of lack of normals? I'm pretty sure I got the number of verticies/triangles right but I'm not sure if I've made mistakes. What is the next step to fully render the model like the first image?
buffer creation:
//Vertex buffer
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
//color buffer
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
//create shaders and attach them to a program object
GLuint program = rigShadersToProgram();
GLuint matrixID = glGetUniformLocation(program, "MVP");
rendering loop:
// Rendering loop
while (!glfwWindowShouldClose(window))
{
//clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
////////////////////////////matrix operations/////////////////////////////////////////
//projection matrix 45 degree FoV, 4:3 ratio, display range 0.1 - 100
glm::mat4 projection = glm::perspective(99.0f, 4.0f/3.0f, 0.1f, 100.0f);
//camera matrix
glm::mat4 view = glm::lookAt(
glm::vec3(2, 1, -1), //camera is at (2,1,-1)
glm::vec3(0, 0 , 0), //looks at origin
glm::vec3(0,1, 0) //head is up
);
//model matrix identity matrix
glm::mat4 model = glm::mat4(1.0f);
//rotate
model = glm::rotate(model, e, glm::vec3(1,2,3));
//model-view-projection
glm::mat4 MVP = projection * view * model;
//////////////////////////////////////////////////////////////////////////////////////
//use the compiled shaders
glUseProgram(program);
//send transformation matrix to currently bound shader
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &MVP[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
//vertex buffer
glVertexAttribPointer(
0, //index
3, //size
GL_FLOAT, //type
GL_FALSE, //normalized?
0, //stride
0 //array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
//color buffer
glVertexAttribPointer(
1, //index
3, //size
GL_FLOAT, //type
GL_FALSE, //normalized?
0, //stride
0 //array buffer offset
);
//draw triangle
glDrawArrays(GL_TRIANGLES, 0, 12722*3);
std::cout << glfwGetTime() << "\n";
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
the model data is stored in an array:
static const GLfloat g_vertex_buffer_data[] = {
-1.557376f, 0.094970f, 0.171995f,
-1.565967f, 0.098142f, 0.171995f,
-1.557376f, 0.094970f, -0.048469f,
-1.565967f, 0.098142f, -0.048469f,
-1.532660f, 0.162907f, -0.048469f,
-1.541251f, 0.166079f, -0.048469f,
-1.444236f, 0.405840f, 0.171996f,
-1.452827f, 0.409013f, 0.171996f,
-1.463533f, 0.352575f, 0.171995f,
-1.472257f, 0.355747f, 0.171995f,
-1.528166f, 0.175331f, 0.011009f,
-1.536757f, 0.178371f, 0.011009f,
-1.538475f, 0.146781f, 0.025019f, ... etc
vertex shader:
#version 430 core
layout(location =0) in vec3 vpos;
layout(location =1) in vec3 vertexColor;
out vec3 fragmentColor;
uniform mat4 MVP;
void main(void)
{
//output position of the vertex in clip space MVP*position
gl_Position = MVP * vec4(vpos,1);
fragmentColor = vertexColor;
};
fragment shader:
#version 430 core
in vec3 fragmentColor;
out vec3 color;
void main()
{
color = fragmentColor;
};

You don't show the actual model loading or rendering code. But what's clear from the screenshot of your program is, that your vertex indexing order is totally messed up. There are vertices connected with each other in your program's drawing that definitely are not connected in the model. Time to recheck the model loader code.
BTW: why did you hardcode the number of vertices to draw in the glDrawArrays call? That doesn't make sense at all.

Related

How to Draw OpenMesh using OpenGL

i'm working on a project where i'm using OpenMesh to read stl and obj files and draw them on the screen using openGL.
i've been doing the following,
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>
OpenMesh::TriMesh_ArrayKernelT<> mesh;
std::vector<point> vertices;
std::vector<point> normals;
void readMesh(std::string file)
{
OpenMesh::IO::read_mesh(mesh, file);
mesh.requestFaceNormals();
mesh.request_vertex_normals();
mesh.updateNormals();
vertices.clear();
normals.clear();
for (auto face : mesh.faces())
{
for (auto vertex : mesh.fv_range(face))
{
auto point = mesh.point(vertex);
auto normal = mesh.normal(face);
vertices.push_back(point);
normals.push_back(normal);
}
}
mesh.releaseFaceNormals();
mesh.releaseVertexNormals();
}
and when drawing i just pass the vertices and normals vectors to the vertex shader like this
void paint()
{
glSetAttributeArray(0, vertices.data());
glSetAttributeArray(1, normals.data());
glDrawArrays(GL_TRIANGLES, 0, vertices.length());
}
where the vertex shader looks like this:
attribute vec3 position;
attribute vec3 normal;
uniform mat4 modelViewMatrix;
void main(void)
{
vec4 color = vec4(0.25, 0.25, 0.25, 0.0);
vec4 P = vec4(position, 0);
vec4 N = vec4(normal, 0);
vec3 L = vec3(20, 20, 20) - position;
vec3 V = -position;
N = normalize(N);
L = normalize(L);
V = normalize(V);
vec3 R = reflect(-L, vec3(N));
vec3 diffuse = max(dot(vec3(N), L), 0.0) * color.rgb;
vec3 specular = pow(max(dot(R, V), 0.0), 0.2) * vec3(0.1, 0.1, 0.1);
color = vec4(color.a * (ambient + diffuse + specular), color.a);
color = clamp(color, 0.0, 1.0);
gl_Color = color;
gl_Position = modelViewMatrix * P;
}
and the fragment shader is:
void main(void)
{
gl_FragColor = gl_Color;
}
this produces pretty good results, but the idea of having another copy of the vertices and normals stored in another location (normals and vertices) to be able to draw the mesh looks very counter-intuitive.
i was wondering if i can use openGL buffers with openMesh to optimize this. i've been searching for anything concerning this topic for a while but found nothing.
See Vertex Specification. You can create 2 Vertex Buffer Object for the verticex cooridantes and nortmal vertors:
GLuint vbos[2];
glGenBuffers(2, vbos);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(normals[0]), normals.data(), GL_STATIC_DRAW);
If you use OpenGL 3.0 or later, then you can specify a Vertex Array Object a nd state the vertex specification:
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
When you want to draw the mesh, then it is sufficient to bind the VAO:
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices.length());
If you use OpenGL 2.0, the you cannot create a VAO, thus you have to specify the arrays of generic vertex attribute data, before drawing the mesh:
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, vertices.length());
Furthermore note, that the attribute indices are not guaranteed to be 0 and 1. The attribute indices can be any arbitrary number.
If you would use GLSL version 3.30 the it would be possible to set the attribute indices in the shader code by Layout Qualifier.
Anyway you an define the attribute indices by glBindAttribLocation before linking the program or retrieve the attribute indices by glGetAttribLocation after linking the program.

Issues adding instancing to a working sprite system

I'm trying to implement instancing into my 2d Game Engine so that it can support particle systems without losing any performance. My class, ISprite, is derived from a working Sprite class. I just went through and removed all the functionality affecting single sprites and replaced it with an instancing plan in mind. Unfortunately, nothing is drawing on the screen.
Here is the relevant information:
Vertex Shader
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec4 colorSource;
layout (location = 3) in mat4 transform;
out vec2 TexCoords;
out vec4 Color;
uniform mat4 uniformView;
uniform mat4 uniformProjection;
void main()
{
gl_Position = uniformProjection * uniformView * transform * vec4(position, 1.0f);
TexCoords = texCoords;
Color = colorSource;
}
Fragment Shader
#version 330 core
in vec2 TexCoords;
in vec4 Color;
out vec4 color;
uniform sampler2D Texture;
uniform vec4 uniformColor;
void main()
{
vec4 texColor = texture(Texture, TexCoords) * Color;
if(texColor.a < 0.1)
discard;
color = texColor;
}
Load - Prepares all sprites for drawing, called once.
void ISprite::Load(Shader spriteShader)
{
spriteShader.Use();
GLfloat vertices[] = {
//X Y Z
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
glGenVertexArrays(1, &vertexArray);
glGenBuffers(1, &positionBuffer);
glGenBuffers(1, &texCoordsBuffer);
glGenBuffers(1, &colorBuffer);
glGenBuffers(1, &matrixBuffer);
glBindVertexArray(vertexArray);
//The vertex data will never change, so send that data now.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//For vertex Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (GLvoid*)0);
//For texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), (GLvoid*)0);
//For Color
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
//For Transformation Matrix
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
for (int i = 0; i < 4; ++i)
{
glEnableVertexAttribArray(3 + i);
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
4 * 4 * sizeof(GLfloat), (GLvoid*)(4 * i * sizeof(GLfloat)));
}
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBindVertexArray(0);
glVertexAttribDivisor(positionBuffer, 0);
glVertexAttribDivisor(texCoordsBuffer, 1);
glVertexAttribDivisor(colorBuffer, 1);
glVertexAttribDivisor(matrixBuffer, 1);
glVertexAttribDivisor(matrixBuffer + 1, 1);
glVertexAttribDivisor(matrixBuffer + 2, 1);
glVertexAttribDivisor(matrixBuffer + 3, 1);
ISprite::shader = &spriteShader;
}
Prepare Draw - called by each sprite, each frame. Sends data to static vectors
void ISprite::prepareDraw(void)
{
//Adds their personal data to vectors shared by class
glm::mat4 transform = calculateTransorm();
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
ISprite::transformMatrices.push_back(transform[i][j]);
}
texture.updateAnimation();
for (int i = 0; i < 12; ++i)
ISprite::textureCoordinatesAll.push_back(texture.textureCoordinates[i]);
ISprite::colorValues.push_back(color.x);
ISprite::colorValues.push_back(color.y);
ISprite::colorValues.push_back(color.z);
ISprite::colorValues.push_back(color.w);
}
Draw Sprites - called once each frame, actually draws the sprites
void ISprite::drawSprites(Texture testTexture)
{
shader->Use();
for (std::vector<ISprite*>::iterator it = Isprites.begin(); it != Isprites.end(); ++it)
(*it)->prepareDraw();
glBindVertexArray(vertexArray);
glBindTexture(GL_TEXTURE_2D, testTexture.ID);
//Bind texture here if you want textures to work. if not, a single texture atlas will be bound
glBindBuffer(GL_ARRAY_BUFFER, texCoordsBuffer);
glBufferData(GL_ARRAY_BUFFER, textureCoordinatesAll.size() * sizeof(GLfloat),
textureCoordinatesAll.data(), GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, colorValues.size() * sizeof(GLfloat),
colorValues.data(), GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBufferData(GL_ARRAY_BUFFER, transformMatrices.size() * sizeof(GLfloat),
transformMatrices.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 6, Isprites.size());
textureCoordinatesAll.clear();
colorValues.clear();
transformMatrices.clear();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
}
There could be a lot of reasons why nothing is rendered. Problems with the transformations, coordinates out of range, etc. But one thing related to instancing definitely looks wrong in the posted code:
glBindVertexArray(0);
glVertexAttribDivisor(positionBuffer, 0);
glVertexAttribDivisor(texCoordsBuffer, 1);
glVertexAttribDivisor(colorBuffer, 1);
...
The first argument to glVertexAttribDivisor() is the location of a vertex attribute, not the name of a buffer. Also, the state set by this call is part of the VAO state, so you should make these calls while the VAO is still bound.
So the calls should look like this:
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 0);
glVertexAttribDivisor(2, 1);
...
glBindVertexArray(0);
where the first arguments to glVertexAttribDivisor() match the location values you also use as the first argument to glVertexAttribPointer() and glEnableVertexAttribArray().
The divisor value for the texture coordinates (attribute 1) should most likely be 0, since you want the texture coordinates to be set per vertex, just like the positions. For the colors and other remaining attributes, 1 is the correct value so that they are applied per instance.
Also, as I mentioned in a comment, you may also want to look into using point sprites. While they do not offer the same flexibility you can get from drawing individual quads, they can often be used for sprites. With point sprites, you only need one vertex per sprite, and the texture coordinates are generated automatically. My answer here gives an outline on how point sprites are used, including how to apply textures to them: Render large circular points in modern OpenGL.

GLM look at object outside of the screen

I have a cube with vertex at 1 and -1 (1 1 1, 1 1 -1, etc).
Currently I'm using only the view matrix and set the projection to be identity:
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
mat4 view = glm::lookAt(vec3(0,0,3),
vec3(0,0,0),
vec3(0,0,1));
mat4 mvp = view;
GLuint location = glGetUniformLocation(p_myGLSL->getProgramID(), "mvp");
glUniformMatrix4fv(location, 1, GL_FALSE, &mvp[0][0]);
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES, 0, countV);
glFlush();
glutSwapBuffers();
Vertex shading code:
layout (location = 0) in vec3 VertexPosition;
uniform mat4 mvp;
void main()
{
gl_Position = mvp * vec4(VertexPosition,1.0);
}
VBO, VAO code:
// fill values into VBO
GLuint positionBufferHandle;
glGenBuffers(1, &positionBufferHandle);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, countV*sizeof(float), positionData, GL_STATIC_DRAW);
// Vertex array object
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray(vaoHandle);
// Read into vertex shader
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0, (GLubyte *) NULL);
glutMainLoop();
Why is it showing a blank screen for now?
P/S: If I create the view matrix manually it works:
mat4 translate = glm::translate(glm::mat4(1), vec3(-centerx, -centery, -centerz));
mat4 scale = glm::scale(glm::mat4(1), vec3(0.2, 0.2, 0.2));
mat4 mvp = scale * translate;
Use vec3(0,1,0) as up vector. When you are looking at (0,0,0) from (0,0,3), you looking in (0,0,-1) direction. The up vector should be perpendicular to this vector, which you can use vec3(0, 1, 0) vector. So, change the view matrix assignment part to:
mat4 view = glm::lookAt(vec3(0,0,3),
vec3(0,0,0),
vec3(0,1,0));
Also, Add #version 430 or whatever GLSL version which you are using to beginning of your vertex shader. layout qualifer is part of OpenGL core, since OpenGL 4.1 not earlier.

Simple GLSL example not showing anything on screen

I am trying to print a simple cube using GLSL but I only get an empty screen. I don't know what I am doing wrong. The vertices, normals, triangles are exported from Blender.
void InitBuffers() {
// monkey vertices, normals
readVerticesNormals();
// cube vertices
glGenVertexArraysAPPLE(1, &CubeVao);
glBindVertexArrayAPPLE(CubeVao);
glGenBuffers(1, &CubeVboPositions);
glBindBuffer(GL_ARRAY_BUFFER,CubeVboPositions);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1,&CubeVboColors);
glBindBuffer(GL_ARRAY_BUFFER, CubeVboColors);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &CubeNormals);
glBindBuffer(GL_ARRAY_BUFFER, CubeNormals);
glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &CubeIbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, CubeIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangles), triangles, GL_STATIC_DRAW);
}
I bind the vertex data to the shader.
glBindAttribLocation(ProgramShader, 0, "position");
glBindAttribLocation(ProgramShader, 1, "color");
glBindAttribLocation(ProgramShader, 2, "normal");
Camera is positioned in (0,0,0) looking towards (0,0,-1). The object, in this case the cube, it positioned at (0,0,-4).
The render function is:
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,0,0);
// set view matrix
ViewMatrix.setView(0,0,0,0,0,-1,0,1,0);
// use shader program
glUseProgram(ProgramShader);
// send uniforms to shader
glUniformMatrix4fv(ProjectionMatrixLocation, 1, false, ProjectionMatrix.m);
glUniformMatrix4fv(ViewMatrixLocation, 1, false, ViewMatrix.m);
glUniformMatrix4fv(ModelMatrixLocation, 1, false, ModelMatrix.m);
glBindVertexArrayAPPLE(CubeVao);
glDrawElements(GL_TRIANGLES, 3*tri_num, GL_UNSIGNED_INT, (void*)0);
glutSwapBuffers();
}
Vertex shader:
attribute vec3 position;
attribute vec3 color;
attribute vec3 normal;
uniform mat4 modelMatrix,viewMatrix,projMatrix;
varying vec4 Normal;
varying vec4 Position;
varying vec4 Color;
void main() {
// position in view space
Position = viewMatrix * modelMatrix * vec4(position, 1.0);
// normal in view space
Normal = normalize(viewMatrix * modelMatrix * vec4(normal, 1.0));
Color = vec4(color, 1.0);
// final position
gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
Fragment shader:
varying vec4 Normal;
varying vec4 Position;
varying vec4 Color;
void main() {
gl_FragColor = Color;
}
Depending how vertices, colors, etc are defined, sizeof(vertices) may just return the size of the pointer. Try:
3*numVertices*sizeof(float)

Drawing Multiple Models in OpenGL 3.x/4.x

I'm working on a rendering engine and so far it's been coming great, but I can not figure out why when I make two drawing calls to render different models, only 1 will show up.
I'm using wxWidgets to handle the window system, the code in question is pasted below. Any suggestions?
Main Rendering Loop
TestShader.Activate();
glUseProgram(TestShader.Program);
ProjectionMatrix = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
int projectionMatrixLocation = glGetUniformLocation(TestShader.Program, "ProjectionMatrix");
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
glm::mat4 ViewMatrix = glm::lookAt(
glm::vec3(position),
glm::vec3(position+direction),
glm::vec3(up)
);
int viewMatrixLocation = glGetUniformLocation(TestShader.Program, "ViewMatrix");
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, glm::value_ptr(ViewMatrix));
TestModel[1].Draw(TestShader, glm::vec3(0,0,-11));
TestModel[0].Draw(TestShader, glm::vec3(0,0,-1));
Refresh(false);
Model Drawing Function
void E_MODEL::Draw(EShader Shader, glm::vec3 Location)
{
if (!Registered) glGenVertexArrays(1, &VAO[0]);
glBindVertexArray(VAO[0]);
if (!Registered) glGenBuffers(1, &VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
if (!Registered) glBufferData(GL_ARRAY_BUFFER, Vertices.size() * sizeof(glm::vec3), &Vertices[0], GL_STATIC_DRAW);
if (!Registered) glGenBuffers(1, &VBO[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
if (!Registered) glBufferData(GL_ARRAY_BUFFER, Normals.size() * sizeof(glm::vec3), &Normals[0], GL_STATIC_DRAW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), Location);
int modelMatrixLocation = glGetUniformLocation(Shader.Program, "modelMatrix");
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, glm::value_ptr(modelMatrix));
glDrawArrays( GL_TRIANGLES, 0, Vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Registered = true;
}
Vertex Shader
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
// Output data ; will be interpolated for each fragment.
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 modelMatrix;
void main(){
gl_Position = ProjectionMatrix * ViewMatrix * modelMatrix * vec4(vertexPosition_modelspace,1);
// The color of each vertex will be interpolated
// to produce the color of each fragment
fragmentColor = vertexColor;
}
Fragment Shader
#version 330 core
// Interpolated values from the vertex shaders
in vec3 fragmentColor;
// Ouput data
out vec3 color;
void main(){
// Output color = color specified in the vertex shader,
// interpolated between all 3 surrounding vertices
color = fragmentColor;
}
glClear clears a buffer. With the GL_COLOR_BUFFER_BIT flag, you are clearing the color buffer. With the GL_DEPTH_BUFFER_BIT flag, you are clearing the depth buffer. By doing this each time you draw a model, the color and depth information written previously is cleared. This means you are erasing the image every time you draw a model.
You typically clear the buffers once per "paint" or "present". That is, you clear once, you draw N times, you present once. What you are doing now is clear, draw, clear, draw... present.
TL;DR: Call glClear once, before all of your drawing, not before each draw.
is it the glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); inside the draw function? maybe move that out to before you make the calls the draw functions?