I'm having trouble getting phong shading to look right. I'm pretty sure there's something wrong with either my OpenGL calls, or the way I'm loading my normals, but I guess it could be something else since 3D graphics and Assimp are both still very new to me. When trying to load .obj/.mtl files, the problems I'm seeing are:
The models seem to be lit too intensely (less phong-style and more completely washed out, too bright).
Faces that are lit seem to be lit equally all over (with the exception of a specular highlight showing only when the light source position is moved to be practically right on top of the model)
Because of problems 1 and 2, spheres look very wrong:
picture of sphere
And things with larger faces look (less-noticeably) wrong too:
picture of cube
I could be wrong, but to me this doesn't look like proper phong shading.
Here's the code that I think might be relevant (I can post more if necessary):
file: assimpRenderer.cpp
#include "assimpRenderer.hpp"
namespace def
{
assimpRenderer::assimpRenderer(std::string modelFilename, float modelScale)
{
initSFML();
initOpenGL();
if (assImport(modelFilename)) // if modelFile loaded successfully
{
initScene();
mainLoop(modelScale);
shutdownScene();
}
shutdownOpenGL();
shutdownSFML();
}
assimpRenderer::~assimpRenderer()
{
}
void assimpRenderer::initSFML()
{
windowWidth = 800;
windowHeight = 600;
settings.majorVersion = 3;
settings.minorVersion = 3;
app = NULL;
shader = NULL;
app = new sf::Window(sf::VideoMode(windowWidth,windowHeight,32), "OpenGL 3.x Window", sf::Style::Default, settings);
app->setFramerateLimit(240);
app->setActive();
return;
}
void assimpRenderer::shutdownSFML()
{
delete app;
return;
}
void assimpRenderer::initOpenGL()
{
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
}
// check the OpenGL context version that's currently in use
int glVersion[2] = {-1, -1};
glGetIntegerv(GL_MAJOR_VERSION, &glVersion[0]); // get the OpenGL Major version
glGetIntegerv(GL_MINOR_VERSION, &glVersion[1]); // get the OpenGL Minor version
std::cout << "Using OpenGL Version: " << glVersion[0] << "." << glVersion[1] << std::endl;
return;
}
void assimpRenderer::shutdownOpenGL()
{
return;
}
void assimpRenderer::initScene()
{
// allocate heap space for VAOs, VBOs, and IBOs
vaoID = new GLuint[scene->mNumMeshes];
vboID = new GLuint[scene->mNumMeshes*2];
iboID = new GLuint[scene->mNumMeshes];
glClearColor(0.4f, 0.6f, 0.9f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
shader = new Shader("shader.vert", "shader.frag");
projectionMatrix = glm::perspective(60.0f, (float)windowWidth / (float)windowHeight, 0.1f, 100.0f);
rot = 0.0f;
rotSpeed = 50.0f;
faceIndex = 0;
colorArrayA = NULL;
colorArrayD = NULL;
colorArrayS = NULL;
normalArray = NULL;
genVAOs();
return;
}
void assimpRenderer::shutdownScene()
{
delete [] iboID;
delete [] vboID;
delete [] vaoID;
delete shader;
}
void assimpRenderer::renderScene(float modelScale)
{
sf::Time elapsedTime = clock.getElapsedTime();
clock.restart();
if (rot > 360.0f)
rot = 0.0f;
rot += rotSpeed * elapsedTime.asSeconds();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -3.0f, -10.0f)); // move back a bit
modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(modelScale)); // scale model
modelMatrix = glm::rotate(modelMatrix, rot, glm::vec3(0, 1, 0));
//modelMatrix = glm::rotate(modelMatrix, 25.0f, glm::vec3(0, 1, 0));
glm::vec3 lightPosition( 0.0f, -100.0f, 0.0f );
float lightPositionArray[3];
lightPositionArray[0] = lightPosition[0];
lightPositionArray[1] = lightPosition[1];
lightPositionArray[2] = lightPosition[2];
shader->bind();
int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix");
int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix");
int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix");
int ambientLocation = glGetUniformLocation(shader->id(), "ambientColor");
int diffuseLocation = glGetUniformLocation(shader->id(), "diffuseColor");
int specularLocation = glGetUniformLocation(shader->id(), "specularColor");
int lightPositionLocation = glGetUniformLocation(shader->id(), "lightPosition");
int normalMatrixLocation = glGetUniformLocation(shader->id(), "normalMatrix");
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]);
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]);
glUniform3fv(lightPositionLocation, 1, lightPositionArray);
for (unsigned int i = 0; i < scene->mNumMeshes; i++)
{
colorArrayA = new float[3];
colorArrayD = new float[3];
colorArrayS = new float[3];
material = scene->mMaterials[scene->mNumMaterials-1];
normalArray = new float[scene->mMeshes[i]->mNumVertices * 3];
unsigned int normalIndex = 0;
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
normalIndex = 0;
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray);
aiColor3D ambient(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
aiColor3D diffuse(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
aiColor3D specular(0.0f, 0.0f, 0.0f);
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
colorArrayA[0] = ambient.r; colorArrayA[1] = ambient.g; colorArrayA[2] = ambient.b;
colorArrayD[0] = diffuse.r; colorArrayD[1] = diffuse.g; colorArrayD[2] = diffuse.b;
colorArrayS[0] = specular.r; colorArrayS[1] = specular.g; colorArrayS[2] = specular.b;
// bind color for each mesh
glUniform3fv(ambientLocation, 1, colorArrayA);
glUniform3fv(diffuseLocation, 1, colorArrayD);
glUniform3fv(specularLocation, 1, colorArrayS);
// render all meshes
glBindVertexArray(vaoID[i]); // bind our VAO
glDrawElements(GL_TRIANGLES, scene->mMeshes[i]->mNumFaces*3, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // unbind our VAO
delete [] normalArray;
delete [] colorArrayA;
delete [] colorArrayD;
delete [] colorArrayS;
}
shader->unbind();
app->display();
return;
}
void assimpRenderer::handleEvents()
{
sf::Event event;
while (app->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
app->close();
}
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
{
app->close();
}
if (event.type == sf::Event::Resized)
{
glViewport(0, 0, event.size.width, event.size.height);
}
}
return;
}
void assimpRenderer::mainLoop(float modelScale)
{
while (app->isOpen())
{
renderScene(modelScale);
handleEvents();
}
}
bool assimpRenderer::assImport(const std::string& pFile)
{
// read the file with some example postprocessing
scene = importer.ReadFile(pFile,
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType);
// if the import failed, report it
if (!scene)
{
std::cerr << "Error: " << importer.GetErrorString() << std::endl;
return false;
}
return true;
}
void assimpRenderer::genVAOs()
{
int vboIndex = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; i++, vboIndex+=2)
{
mesh = scene->mMeshes[i];
indexArray = new unsigned int[mesh->mNumFaces * sizeof(unsigned int) * 3];
// convert assimp faces format to array
faceIndex = 0;
for (unsigned int t = 0; t < mesh->mNumFaces; ++t)
{
const struct aiFace* face = &mesh->mFaces[t];
std::memcpy(&indexArray[faceIndex], face->mIndices, sizeof(float) * 3);
faceIndex += 3;
}
// generate VAO
glGenVertexArrays(1, &vaoID[i]);
glBindVertexArray(vaoID[i]);
// generate IBO for faces
glGenBuffers(1, &iboID[i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * mesh->mNumFaces * 3, indexArray, GL_STATIC_DRAW);
// generate VBO for vertices
if (mesh->HasPositions())
{
glGenBuffers(1, &vboID[vboIndex]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex]);
glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, mesh->mVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)0);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
// generate VBO for normals
if (mesh->HasNormals())
{
normalArray = new float[scene->mMeshes[i]->mNumVertices * 3];
unsigned int normalIndex = 0;
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
normalIndex = 0;
glGenBuffers(1, &vboID[vboIndex+1]);
glBindBuffer(GL_ARRAY_BUFFER, vboID[vboIndex+1]);
glBufferData(GL_ARRAY_BUFFER, mesh->mNumVertices * sizeof(GLfloat) * 3, normalArray, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)1);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
delete [] normalArray;
}
// tex coord stuff goes here
// unbind buffers
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
delete [] indexArray;
}
vboIndex = 0;
return;
}
}
file: shader.vert
#version 150 core
in vec3 in_Position;
in vec3 in_Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform vec3 lightPosition;
uniform mat3 normalMatrix;
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
void main()
{
// derive MVP and MV matrices
mat4 modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix;
mat4 modelViewMatrix = viewMatrix * modelMatrix;
// get surface normal in eye coordinates
vVaryingNormal = normalMatrix * in_Normal;
// get vertex position in eye coordinates
vec4 vPosition4 = modelViewMatrix * vec4(in_Position, 1.0);
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// get vector to light source
vVaryingLightDir = normalize(lightPosition - vPosition3);
// Set the position of the current vertex
gl_Position = modelViewProjectionMatrix * vec4(in_Position, 1.0);
}
file: shader.frag
#version 150 core
out vec4 out_Color;
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform vec3 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
void main()
{
// dot product gives us diffuse intensity
float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
// multiply intensity by diffuse color, force alpha to 1.0
out_Color = vec4(diff * diffuseColor, 1.0);
// add in ambient light
out_Color += vec4(ambientColor, 1.0);
// specular light
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if (diff != 0)
{
float fSpec = pow(spec, 128.0);
// Set the output color of our current pixel
out_Color.rgb += vec3(fSpec, fSpec, fSpec);
}
}
I know it's a lot to look through, but I'm putting most of the code up so as not to assume where the problem is.
Are you doing the right thing for the normal matrix? This looks quite bizarre to me.
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumVertices * 3; j+=3, normalIndex++)
{
normalArray[j] = scene->mMeshes[i]->mNormals[normalIndex].x; // x
normalArray[j+1] = scene->mMeshes[i]->mNormals[normalIndex].y; // y
normalArray[j+2] = scene->mMeshes[i]->mNormals[normalIndex].z; // z
}
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, normalArray);
Why does the normalMatrix have anything to do with the vertices of the mesh? It should be identical to your modelMatrix (provided that you're not doing any non-uniform scaling).
Related
I'm trying to show the normals of some vertices of the mesh when I select them but accordingly to the position of the cam these normals are displayed or not and the big problem is that they are displayed when they shouldn't (i.e. when i select vertices of the tibia but i'm looking at the calf so they should be hidden by the leg) and not displayed when they should be displayed.
I could be wrong but it's like some geometry of the model is drawn above the line. Moreover, if before calling the draw calls i disable the depth test it works (even if the problem of being showed when they shouldn't isn't resolved obviously). That's some images to give you an idea of what I mean.
WITH DEPTH TEST OFF:
DEPT TEST ON:
That's the code:
void StatusManager::Render() {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!animatedModel)
return;
Update();
// draw wireframe if enabled
if (wireframeEnabled)
DrawWireframe();
if (visualMode == Mode_Texture) {
// draw model
if (lightingMode == Mode_Flat)
DrawModel(modelFlatShader);
else if (lightingMode == Mode_Smooth)
DrawModel(modelSmoothShader);
else
DrawModel(modelNoLightShader);
}
else if (visualMode == Mode_CurrentBoneIDInfluence) {
DrawModel(currentBoneShader);
}
else if (visualMode == Mode_NumBones)
{
DrawModel(numBonesShader);
}
else
{
DrawModel(modelGreyShader);
}
// render selected vertices
DrawSelectedVertices();
if (!info.hitPoint)
return;
//DrawHotPoint();
if (selectionMode == Mode_Vertex)
DrawHoveredPoint();
if (selectionMode == Mode_Edge)
DrawHoveredLine();
if (selectionMode == Mode_Face)
DrawHoveredFace();
}
void StatusManager::DrawWireframe() {
wireframeShader.use();
glLineWidth(1.0f);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
wireframeShader.setMat4("modelView", modelView);
wireframeShader.setMat4("projection", projection);
// pass bones matrices to the shader
auto transforms = animator.GetFinalBoneMatrices();
for (int i = 0; i < transforms.size(); ++i)
wireframeShader.setMat4("finalBonesMatrices[" + std::to_string(i) + "]", transforms[i]);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
animatedModel.value().Draw(wireframeShader);
}
void StatusManager::DrawModel(Shader& modelShader) {
modelShader.use();
// model/view/projection transformations
modelShader.setMat4("modelView", camera.viewMatrix);
modelShader.setMat4("projection", projection);
if (visualMode == Mode_Texture)
modelShader.setVec3("light_pos", lightPos);
else if (visualMode == Mode_CurrentBoneIDInfluence)
modelShader.setInt("currentBoneID", currentBoneID);
// pass bones matrices to the shader
auto transforms = animator.GetFinalBoneMatrices();
for (int i = 0; i < transforms.size(); ++i)
modelShader.setMat4("finalBonesMatrices[" + std::to_string(i) + "]", transforms[i]);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
/*if (pause)
bakedModel.value().Draw(modelShader);
else*/
animatedModel.value().Draw(modelShader);
}
void StatusManager::DrawHoveredFace() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
//vertex
float hoveredVertices[9] = {
m.vertices[f.indices[0]].Position.x, m.vertices[f.indices[0]].Position.y, m.vertices[f.indices[0]].Position.z,
m.vertices[f.indices[1]].Position.x, m.vertices[f.indices[1]].Position.y, m.vertices[f.indices[1]].Position.z,
m.vertices[f.indices[2]].Position.x, m.vertices[f.indices[2]].Position.y, m.vertices[f.indices[2]].Position.z,
};
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(hoveredVertices), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glDrawArrays(GL_TRIANGLES, 0, 3);
//unbind
glBindVertexArray(0);
}
void StatusManager::DrawHoveredPoint() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
int index = getClosestVertexIndex(info.hitPoint.value(), m, f);
//vertex
float hoveredVertices[3] = { m.vertices[index].Position.x, m.vertices[index].Position.y, m.vertices[index].Position.z };
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(float), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glPointSize(8.0f);
glDrawArrays(GL_POINTS, 0, 1);
//unbind
glBindVertexArray(0);
}
void StatusManager::DrawHotPoint()
{
float hotVertices[3] = { hotPoint.x, hotPoint.y, hotPoint.z };
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(float), &hotVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glPointSize(8.0f);
glDrawArrays(GL_POINTS, 0, 1);
//unbind
glBindVertexArray(0);
}
void StatusManager::UpdateSelectedVertices()
{
selectedVertices.clear();
for (Vertex* v : selectedVerticesPointers)
selectedVertices.push_back(*v);
}
void StatusManager::DrawHoveredLine() {
assert(bakedModel.has_value());
assert(info.hitPoint.has_value());
Mesh& m = bakedModel.value().meshes[info.meshIndex];
Face& f = info.face.value();
auto line = getClosestLineIndex(info.hitPoint.value(), m, f);
//vertex
float hoveredVertices[6] = {
m.vertices[line.v1].Position.x, m.vertices[line.v1].Position.y, m.vertices[line.v1].Position.z,
m.vertices[line.v2].Position.x, m.vertices[line.v2].Position.y, m.vertices[line.v2].Position.z
};
hoverShader.use();
glBindVertexArray(HVAO);
glBindBuffer(GL_ARRAY_BUFFER, HVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(hoveredVertices), &hoveredVertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, 0.0);
// model/view/projection transformations
glm::mat4 modelView = camera.viewMatrix;
hoverShader.setMat4("modelView", modelView);
hoverShader.setMat4("projection", projection);
glLineWidth(3.0f);
glDrawArrays(GL_LINES, 0, 2);
glLineWidth(1.0f);
//unbind
glBindVertexArray(0);
}
normalShader just for completeness
VERTEX SHADER:
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 norm;
layout(location = 2) in ivec4 boneIds;
layout(location = 3) in vec4 weights;
layout(location = 4) in int numBones;
uniform mat4 projection;
uniform mat4 modelView;
uniform mat4 finalBonesMatrices[100];
out VS_OUT {
vec4 normal;
} vs_out;
void main()
{
mat4 cumulativeMatrix = mat4(1.0);
if (numBones>0)
cumulativeMatrix = mat4(0.0);
for(int i = 0 ; i < numBones ; i++)
{
cumulativeMatrix += (finalBonesMatrices[boneIds[i]] * weights[i]);
}
gl_Position = projection * modelView * cumulativeMatrix * vec4(pos, 1.0);
vs_out.normal = normalize(modelView * cumulativeMatrix * vec4(norm, 0.0));
}
GEOMETRY SHADER:
#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;
uniform float normal_length;
in VS_OUT {
vec4 normal;
} gs_in[];
void main() {
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[0].gl_Position + gs_in[0].normal * normal_length;
EmitVertex();
EndPrimitive();
}
FRAGMENT SHADER:
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1, 0, 0, 1);
}
If you need other piece of code tell me and I'll provide it, but I think I posted all the code and images you need.
Ok I don't know how I didn't noticed it, but yes, the problem was that I wasn't applying the projection matrix to the normal vector. Thanks Spektre to point this out.
I am using Assimp to load models to render in OpenGL but am running into an issue where chunks/pieces of a mesh don't render.
Example:
What model is supposed to look like:
What I end up rendering:
As you can see, some of the model is rendering properly, but not all.
I have verified multiple times that the meshes being loaded from assimp are loading the correct vertices and indices into my "Mesh" class. Here is my code for loading a model:
This function will recursively call itself for all child nodes and load each mesh inside the node. Each mesh will then be transformed into my own "Mesh" class by creating a vector of vertices and faces.
void Model::LoadAssimpNode(aiNode* node, const aiScene* scene)
{
// Process assimp meshes
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back(this->LoadAssimpMesh(mesh, scene));
}
// Recursivley processes child nodes
for (unsigned int i = 0; i < node->mNumChildren; i++)
{
this->LoadAssimpNode(node->mChildren[i], scene);
}
}
Mesh Model::LoadAssimpMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<sVertex> vertices;
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
sVertex vertex;
vertex.x = mesh->mVertices[i].x;
vertex.y = mesh->mVertices[i].y;
vertex.z = mesh->mVertices[i].z;
vertex.nx = mesh->mNormals[i].x;
vertex.ny = mesh->mNormals[i].y;
vertex.nz = mesh->mNormals[i].z;
if (mesh->mTextureCoords[0])
{
vertex.u0 = mesh->mTextureCoords[0][i].x;
vertex.v0 = mesh->mTextureCoords[0][i].y;
}
vertices.push_back(vertex);
}
std::vector<sTriangle> faces;
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
sTriangle face;
aiFace assimpFace = mesh->mFaces[i];
if (assimpFace.mNumIndices != 3)
{
std::cout << "Face is not a triangle!" << std::endl;
}
for (unsigned int j = 0; j < assimpFace.mNumIndices; j++)
{
face.vertIndex[j] = assimpFace.mIndices[j];
}
faces.push_back(face);
}
std::vector<Texture> textures;
if (mesh->mMaterialIndex >= 0)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// Sampler names should adhere to the following convention:
// Diffuse: texure_diffuseN
// Specular: texture_specularN
// Normal: texture_normalN
// Where N = texture numbers
for (Texture texture : this->LoadAssimpMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"))
{
this->loadedTextures.insert(std::make_pair(texture.path.C_Str(), texture));
textures.push_back(texture);
}
for (Texture texture : this->LoadAssimpMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"))
{
this->loadedTextures.insert(std::make_pair(texture.path.C_Str(), texture));
textures.push_back(texture);
}
}
return Mesh(vertices, faces, textures);
}
The sVertex and sTriangle structs are defined as:
struct sVertex
{
float x, y, z;
float nx, ny, nz;
float u0, v0;
};
struct sTriangle
{
unsigned int vertIndex[3];
};
Now that the model is effectively loaded from assimp, we now call the SetupMesh() function which sets up the meshes' respective VAO, VBO and EBO:
void Mesh::SetupMesh()
{
// Generate IDs for our VAO, VBO and EBO
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glBindVertexArray(this->VAO);
// Now ANY state that is related to vertex or index buffer
// and vertex attribute layout, is stored in the 'state'
// of the VAO...
// Tell open GL where to look for for vertex data
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(sVertex), &this->vertices[0], GL_STATIC_DRAW);
// Tell open GL where our index buffer begins (AKA: where to look for faces)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->faces.size() * sizeof(sTriangle), &this->faces[0], GL_STATIC_DRAW);
// Set the vertex attributes for this shader
// Layout information can be found in the vertex shader, currently:
// 0 = position
// 1 = normals
// 2 = texture coordinates
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*) offsetof(sVertex, x));
glEnableVertexAttribArray(1); // normal
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*) offsetof(sVertex, nx));
glEnableVertexAttribArray(2); // textureCoordinates
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*)offsetof(sVertex, u0));
// Now that all the parts are set up, unbind buffers
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
Once this is all setup, I will now call the Draw method for each mesh to render in my render loop:
void Mesh::Draw(const CompiledShader& shader)
{
glm::mat4 matModel = glm::mat4(1.0f);
glm::mat4 matTranslate = glm::translate(glm::mat4(1.0f), this->positionXYZ); // Translation matrix
glm::mat4 rotateX = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.x, glm::vec3(1.0f, 0.0f, 0.0f)); // X axis rotation
glm::mat4 rotateY = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.y, glm::vec3(0.0f, 1.0f, 0.0f)); // Y axis rotation
glm::mat4 rotateZ = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.z, glm::vec3(0.0f, 0.0f, 1.0f)); // Z axis rotation
glm::mat4 matScale = glm::scale(glm::mat4(1.0f), glm::vec3(this->scale, this->scale, this->scale)); // Scale the mesh
glm::mat4 matInvTransposeModel = glm::inverse(glm::transpose(matModel));
// Apply all the transformations to our matrix
matModel = matModel * matTranslate;
matModel = matModel * rotateZ;
matModel = matModel * rotateY;
matModel = matModel * rotateX;
matModel = matModel * matScale;
glUseProgram(shader.ID);
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "matModel"), 1, GL_FALSE, glm::value_ptr(matModel)); // Tell shader the model matrix (AKA: Position orientation and scale)
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "matModelInverseTranspose"), 1, GL_FALSE, glm::value_ptr(matInvTransposeModel));
// Draw the mesh
glBindVertexArray(this->VAO);
glDrawElements(GL_TRIANGLES, this->faces.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
My shaders are very simple where the color of a pixel is equal to the vertex's normal:
Vertex Shader:
#version 420
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 textureCoordinates;
uniform mat4 matModel;
uniform mat4 matView;
uniform mat4 matProjection;
uniform mat4 matModelInverseTranspose; // For normal calculation
out vec4 fVertWorldLocation;
out vec4 fNormal;
out vec2 TextureCoordinates;
void main()
{
mat4 MVP = matProjection * matView * matModel;
gl_Position = MVP * vec4(position, 1.0f);
TextureCoordinates = textureCoordinates;
// The location of the vertex in "world" space (not screen space)
fVertWorldLocation = matModel * vec4(position, 1.0f);
// Calculate the normal based on any rotation we've applied.
// This inverse transpose removes scaling and tranlation (movement)
// from the matrix.
fNormal = matModelInverseTranspose * vec4(normal, 1.0f);
};
Fragment Shader:
#version 420
in vec2 TextureCoordinates;
in vec4 fNormal;
out vec4 Color;
uniform sampler2D texture_diffuse;
void main()
{
//Color = vec4(texture(texture_diffuse, TextureCoordinates));
//Color = vec4(TextureCoordinates, 1.0f, 1.0f);
Color = fNormal;
}
Sorry for the insane length of this post, but I feel that all of it was necessary to get my point across.
If anyone could point out what I am doing wrong here it would be greatly appreciated! I feel like I need an extra pair of eyes here because I have read my code over countless times and can't seem to come up with anything.
Made a stupid mistake, I was under the impression that the "count" argument in the glDrawElements() function wanted the number of faces NOT the number of indices.
The problem was fixed by changing my glDrawElements call from:
glDrawElements(GL_TRIANGLES, this->faces.size(), GL_UNSIGNED_INT, 0);
To this:
glDrawElements(GL_TRIANGLES, this->faces.size() * 3, GL_UNSIGNED_INT, 0);
I am trying to draw filled circle in modern opengl using GL_TRIANGLE. I am filling circle array for circle vertices, and then I am filling points array using circle vertices to use vertices in triangle.I am using vec4(homogeneous coordinates) and setting vertices z-axis value to 0.0 and using default projection which should be from -1 to 1 ranges for each axis. But somehow, I am getting all screen painted with color instead of circle. Weirdly when I set z-axis value of points other than [0-0.4] range, I can get circle be drawn and when I increase the value of z, it acts like perspective and no matter what I have set to radius, it is getting smaller when z is increased. I could not figure out why z value acts like that.
using namespace Angel;
const int NumVertices = 90;
const double PI = 3.141592653589793238463;
const GLint width = 500;
const GLint height = 500;
vec4 points[NumVertices];
vec4 colors[NumVertices];
vec4 circle[30];
vec4 color = { 1.0,0.0,0.0,1.0 };
vec4 center = { 0.0,0.0,0.0,1.0 };
GLfloat radius = 0.5;
int Index = 0;
void triangle(int b, int c) {
colors[Index] = color; points[Index] = center; Index++;
colors[Index] = color; points[Index] = circle[b%30]; Index++;
colors[Index] = color; points[Index] = circle[c%30]; Index++;
}
void fill() {
for (int i = 0; i < 30; i++)
{
float angle = 2 * PI * i / 30;
vec4 point;
point.x = center.x + (GLfloat)cos(angle) * radius;
point.y = center.y + (GLfloat)sin(angle) * radius;
point.z = 0.0 ; // PROBLEM !!
circle[i] = point;
}
for (int i = 0; i <= 29; i++) {
triangle(i, i + 1);
}
}
void init()
{
fill();
// Create a vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
// Load shaders and use the resulting shader program
GLuint program = InitShader("vshader.glsl", "fshader.glsl");
glUseProgram(program);
// set up vertex arrays
GLuint vPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0));
GLuint vColor = glGetAttribLocation(program, "vColor");
glEnableVertexAttribArray(vColor);
glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(points)));
glEnable(GL_DEPTH_TEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glutSwapBuffers();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutInitWindowPosition(100, 100);
glutCreateWindow("PirateFace");
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
vertex shader :
#version 150
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
void main()
{
gl_Position = vPosition;
color = vColor;
}
fragment shader :
#version 150
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}
I am using vec4(homogeneous coordinates)
You need to properly initialize the w component of your vec4 values to 1.0.
Note that you do not need to store homogenous coordinates in your input vertex arrays in most scenarios. You can keep the in vec4 in the vertex shader and just use 3-dimensional vectors as input, and the GL will automatically extend the vector to (x,y,z,1).
I'm attempting to render a triangle using VBOs in OpenGL via C++.
First, I identify my variables:
CBuint _vao;
CBuint _vbo;
CBuint _ebo;
struct Vertex
{
CBfloat position[3];
};
Then, I set the positions for each vertex to form a geometrical triangle:
Vertex v[3];
v[0].position[0] = 0.5f;
v[0].position[1] = 0.5f;
v[0].position[2] = 0.0f;
v[1].position[0] = 0.5f;
v[1].position[1] = -0.5f;
v[1].position[2] = 0.0f;
v[2].position[0] = -0.5f;
v[2].position[1] = -0.5f;
v[2].position[2] = 0.0f;
Simple enough, right?
Then, I declare my indices for the EBO/IBO:
unsigned short i[] =
{
0, 1, 2
};
Now that I have all the attribute data needed for buffering, I bind the VAO as well as the VBOs:
// Generate vertex elements
glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ebo);
// VAO
glBindVertexArray(_vao);
// VBO
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 9, &v, GL_STATIC_DRAW);
// EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * 3, &i, GL_STATIC_DRAW);
// Location 0 - Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glBindVertexArray(0);
Next, I render them:
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
I then use the vertex shader:
#version 330 core
// Vertex attributes
layout(location = 0) in vec3 position;
// Node parses
out vec3 Fragpos;
// Uniforms
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
// Vertex loop
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
Fragpos = vec3(model * vec4(position, 1.0f));
}
To simply calculate the model position as well as the camera view. The fragment shader is again, quite simplistic:
#version 330 core
// Node parses
out vec4 color;
in vec3 Fragpos;
// Camera data
uniform vec3 view_loc;
// Global uniforms
uniform struct GLOBAL
{
float ambient_coefficient;
vec3 ambient_colour;
} _global;
// Main loop
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
The uniforms work perfectly fine as I've been using this shader code for previous projects. So what could the problem be? The triangle simply does not render. I can't think of anything that's causing this, any ideas?
Edit: Just to narrow things down, I also use these variables to handle the model matrix that are being parsed to and from the vertex shader:
CBuint _u_model;
mat4 _model;
vec3 _position;
vec4 _rotation;
vec3 _scale;
Then inside the constructor, I initialize the variables like so:
_model = mat4::identity();
_position = vec3(0.0f, 0.0f, 0.0f);
_rotation = vec4(0.0f, 1.0f, 0.0f, 0.0f);
_scale = vec3(1.0f, 1.0f, 1.0f);
_u_model = glGetUniformLocation(shader->_program, "model");
And finally, I update the model matrix using this formula:
_model = translate(_position) *
rotate(_rotation.data[0], _rotation.data[1], _rotation.data[2], _rotation.data[3]) *
scale(_scale);
Edit 2: This is the camera class I use for the MVP:
class Camera : public object
{
private:
CBbool _director;
CBfloat _fov;
CBfloat _near;
CBfloat _far;
CBfloat _speed;
Math::vec3 _front;
Math::vec3 _up;
Math::mat4 _projection;
Math::mat4 _view;
CBuint _u_projection;
CBuint _u_view;
public:
Camera(Shader* shader, Math::vec3 pos, float fov, float n, float f, bool dir) : _speed(5.0f)
{
_model = Math::mat4::identity();
_projection = Math::mat4::identity();
_view = Math::mat4::identity();
_position = pos;
_fov = fov;
_near = n;
_far = f;
_director = dir;
_front = vec3(0.0f, 0.0f, -1.0f);
_up = vec3(0.0f, 1.0f, 0.0f);
_u_projection = glGetUniformLocation(shader->_program, "projection");
_u_view = glGetUniformLocation(shader->_program, "view");
_u_model = glGetUniformLocation(shader->_program, "view_loc");
}
~Camera() {}
inline CBbool isDirector() { return _director; }
inline void forward(double delta) { _position.data[2] -= _speed * (float)delta; }
inline void back(double delta) { _position.data[2] += _speed * (float)delta; }
inline void left(double delta) { _position.data[0] -= _speed * (float)delta; }
inline void right(double delta) { _position.data[0] += _speed * (float)delta; }
inline void up(double delta) { _position.data[1] += _speed * (float)delta; }
inline void down(double delta) { _position.data[1] -= _speed * (float)delta; }
virtual void update(double delta)
{
_view = Math::lookat(_position, _position + _front, _up);
_projection = Math::perspective(_fov, 900.0f / 600.0f, _near, _far);
}
virtual void render()
{
glUniformMatrix4fv(_u_view, 1, GL_FALSE, _view);
glUniformMatrix4fv(_u_projection, 1, GL_FALSE, _projection);
glUniform3f(_u_model, _position.data[0], _position.data[1], _position.data[2]);
}
};
As Amadeus mentioned, I simply had to use gl_Position = vec4(position, 1.0f); for it to render. No idea why, but now's the time to find out! Thanks for your time.
I want to draw simple square. First I use glDrawArrays but now I want to change it to glDrawElements. I read bunch of tutorials but for some reason it doesn't render anything.
Renderer class:
class Renderer_t {
private:
...
glm::mat4 projectionMatrix; // Store the projection matrix
glm::mat4 viewMatrix; // Store the view matrix
glm::mat4 modelMatrix; // Store the model matrix
unsigned int vaoID[1]; // Our Vertex Array Object
unsigned int vboID[3]; // Our Vertex Buffer Object
...
};
Initialize of scene:
Renderer_t::Renderer_t(SDL_Window* window): scene(nullptr), width(800), height(600) {
LOG(info) << "Renderer_t constructor";
gl = SDL_GL_CreateContext(window);
glbinding::Binding::initialize();
//Initialize scene
glClearColor(0.4f, 0.6f, 0.9f, 0.0f);
shader = new Shader("../assets/shader.vert", "../assets/shader.frag");
float ratio = width/height;
projectionMatrix = glm::perspective(60.0f, ratio, 0.1f, 100.f); // Create our perspective projection matrix
int vertnum = 4 * 3; //6x
//Create square
float* vertices = new float[vertnum]; // Vertices for our square
float* colors = new float[vertnum]; // Colors for our vertices
unsigned int* indices = new unsigned int[6];
indices[0] = 0; indices[0] = 1; indices[0] = 2;
indices[0] = 2; indices[0] = 3; indices[0] = 0;
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner
colors[0] = 1.0; colors[1] = 1.0; colors[2] = 1.0; // Bottom left corner
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner
colors[3] = 1.0; colors[4] = 0.0; colors[5] = 0.0; // Top left corner
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
colors[6] = 0.0; colors[7] = 1.0; colors[8] = 0.0; // Top Right corner
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner
colors[9] = 0.0; colors[10] = 0.0; colors[11] = 1.0; // Bottom right corner
/*
vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; // Bottom left corner
colors[12] = 1.0; colors[13] = 1.0; colors[14] = 1.0; // Bottom left corner
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner
colors[15] = 0.0; colors[16] = 1.0; colors[17] = 0.0; // Top Right corner
*/
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(3, &vboID[0]); // Generate our Vertex Buffer Objects
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, vertnum * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Enable our Vertex Array Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[1]); // Bind our second Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, vertnum * sizeof(GLfloat), colors, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(1); // Enable the second vertex attribute array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)2, 3, GL_INT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Disable our Vertex Buffer Object
delete[] vertices; // Delete our vertices from memory
delete[] colors; // Delete our vertices from memory
delete[] indices;
LOG(info) << "Renderer_t constructor done";
}
Rendering:
void Renderer_t::render() {
LOG(info) << "Renderer_t.render()";
glViewport(0, 0, width, height); // Set the viewport size to fill the window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers
viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.f)); // Create our view matrix
modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)); // Create our model matrix
shader->bind(); // Bind our shader
int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix"); // Get the location of our projection matrix in the shader
int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix"); // Get the location of our view matrix in the shader
int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix"); // Get the location of our model matrix in the shader
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]); // Send our projection matrix to the shader
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); // Send our view matrix to the shader
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); // Send our model matrix to the shader
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
// glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0); // Unbind our Vertex Array Object
shader->unbind(); // Unbind our shader
LOG(info) << "Renderer_t.render() done";
}
I also use shaders:
shader.vert
version 130
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
in vec3 in_Position;
in vec3 in_Color;
out vec3 pass_Color;
void main(void)
{
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0);
pass_Color = in_Color;
}
shader.fraq
#version 130
in vec3 pass_Color;
out vec4 out_Color;
void main(void)
{
out_Color = vec4(pass_Color, 1.0);
}
Just so you know, a triangle list with elements: 0,1,2 0,2,3 is the same thing as glDrawArrays(GL_TRIANGLE_FAN, 0, 4). You could just use a triangle fan here and not have to use indices at all.
Your actual problem is that you keep writing each element in your element array to [0].
Right now your code reads:
indices[0] = 0; indices[0] = 1; indices[0] = 2;
indices[0] = 2; indices[0] = 3; indices[0] = 0;
However, to function correctly it needs to read:
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 2; indices[4] = 3; indices[5] = 0; // This is equivalent to 0, 2, 3
Everything in BDL's answer are also important things you should note.
You try to bind the ELEMENT_ARRAY_BUFFER to a varying of your shader
glVertexAttribPointer((GLuint)2, 3, GL_INT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
Index buffers do not have to be bound to a shader, since they are not directly used as input to them. Beside this, your shader has only two in-variables (most probably numbered 0 and 1), so using 2 will never work.
Another hint:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
in your render() is not necessary, since the binding is already stored in the vao during the initialization. But this should not effect the output.