My model looks stretched because of corrupted data in vertex shader attribute location
Here's the vertex shader code:
#version 330 core
layout (location = 0) in vec3 vertPos;
layout (location = 1) in vec3 vertNormal;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in vec4 boneWeigths;
layout (location = 4) in ivec4 boneIDs;
out vec3 vNormal;
out vec3 fragPos;
out vec2 fragTexCoord;
const int MAX_BONES = 100;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 boneTransforms[MAX_BONES];
void main()
{
mat4 boneTx = boneTransforms[boneIDs[0]] * boneWeigths[0]
+ boneTransforms[boneIDs[1]] * boneWeigths[1]
+ boneTransforms[boneIDs[2]] * boneWeigths[2]
+ boneTransforms[boneIDs[3]] * boneWeigths[3];
vec4 pos = boneTx * vec4(vertPos, 1.0f);
gl_Position = MVP * pos;
vec4 normal = boneTx * vec4(vertNormal, 0.0f);
vNormal = normalize(vec3(M * normal));
fragPos = vec3(M * pos);
fragTexCoord = vec2(texCoord.x, texCoord.y);
}
The problem seems to be corrupted data in boneIDs (boneIDs data is fine on CPU, but getting corrupted data in shader). I tried hard-coding boneIDs data in shader, and that works fine.
Here's the code for VAO:
// create buffers/arrays
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
unsigned int sz = sizeof(BoneVertex);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(BoneVertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// set the vertex attribute pointers
// vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(3 * sizeof(float)));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(6 * sizeof(float)));
// bone weights
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(8 * sizeof(float)));
// bone ids
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_INT, GL_FALSE, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
glBindVertexArray(0);
BoneVertex structure:
struct BoneVertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 textureCoords;
glm::vec4 boneWeights;
glm::ivec4 boneIDs;
}
This is weird, because the first 3 attributes data seems fine. The problem is with boneIDs and boneWeights
Is this somehow related to padding, and how data is arranged in a structure? Or am I missing something else?
Thanks
boneIDs is a vertex shader input with an integral data type:
layout (location = 4) in ivec4 boneIDs;
If you want to specify the generic vertex attribute data for an integral attribute, then you have to use glVertexAttribIPointer (focus on I) rather than glVertexAttribPointer (see glVertexAttribPointer).
Note, the type argument doesn't specify the type of the target attribute, it specifies the element type of the source data array. glVertexAttribPointer converts the source data array to floating point values, but glVertexAttribIPointer specifies the array for integral target attributes.
glVertexAttribPointer(4, 4, GL_INT, GL_FALSE, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
glVertexAttribIPointer(4, 4, GL_INT, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
Related
I have this tesselation evaluation shader:
\\ vertex
#version 410 core
#define SIZE 6
layout (location = 0) in vec2 x;
layout (location = 1) in vec2 h;
layout (location = 2) in float f[SIZE];
out TC_DATA
{
vec2 x;
vec2 h;
float f[SIZE];
} tc_out;
void main()
{
tc_out.x = x;
tc_out.h = h;
tc_out.f = f;
}
\\ tess control
#version 410
layout (vertices = 1) out;
#define SIZE 6
uniform int outer0;
uniform int outer1;
uniform int outer2;
uniform int inner;
in TC_DATA
{
vec2 x;
vec2 h;
float f[SIZE];
} tc_in[];
out TE_DATA
{
vec2 x;
vec2 h;
float f[SIZE];
} te_out[];
void main()
{
if (gl_InvocationID == 0)
{
gl_TessLevelInner[0] = inner;
gl_TessLevelOuter[0] = outer0;
gl_TessLevelOuter[1] = outer1;
gl_TessLevelOuter[2] = outer2;
}
te_out[gl_InvocationID].x = tc_in[gl_InvocationID].x;
te_out[gl_InvocationID].h = tc_in[gl_InvocationID].h;
// te_out[gl_InvocationID].f = tc_in[gl_InvocationID].f; // <---- uncommenting this line crashes the app
}
\\ tess evaluation
#version 410
layout (triangles) in;
out vec4 fColor;
void main()
{
gl_Position = vec4(1.0);
fColor = vec4(1.0);
}
\\ fragment
#version 410 core
in vec4 fColor;
out vec4 oColor;
void main()
{
oColor = fColor;
}
The vertex specification:
struct Vertex
{
glm::vec2 x;
glm::vec2 h;
std::array<float, 6> f;
};
std::vector<Vertex> vertices;
// ....
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, x));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, h));
glVertexAttribPointer(2, 6, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, f));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
The render part:
glPatchParameteri(GL_PATCH_VERTICES, 1);
glBindVertexArray(vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(decltype(vertices)::value_type), vertices.data(), GL_DYNAMIC_DRAW);
glDrawArrays(GL_PATCHES, 0, vertices.size());
I am trying to pass an array float f[6] and I crash my app if I don't comment the line indicated in the tesselation control shader. I don't understand what I'm doing wrong. I know for sure it is not the c++ part of the code. There are no errors when compiling the shaders or linking the program (opengl program).
The size argument of glVertexAttribPointer must be 1, 2, 3 or 4. Passing 6 to the size argument generates a GL_INVALID_VALUE error.
If the type of the vertex shader attribute is an array, each element of the array has a separate attribute index. The attribute layout (location = 2) in float f[SIZE]; has the attribute indices from 2 to 7:
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*)offsetof(Vertex, f));
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*)(offsetof(Vertex, f) + 4));
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*)(offsetof(Vertex, f) + 8));
// [...]
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
// [...]
I was trying to implement normal mapping on a simple cube but since i had troubles with my normals i wanted to try to display them using a geometry shader. Following learnopengl tutorial, it basically calls mesh.render() twice, the first time to draw the model and the second time to display normals. When i try to do the same i get this
The cube seems well drawn but it has a weird white rectangle in front of it and i don't know why. I don't know if it's a problem of drawings or if it's the geometry shader, so i'll post both.
My code:
glutDisplayFunc(MyRenderScene);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glGenVertexArrays(1,&global.gVAO);
glGenBuffers(1, &global.VBO);
glBindVertexArray(global.VAO);
glBindBuffer(GL_ARRAY_BUFFER, global.VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &global.IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glGenVertexArrays(1,&global.gVAO);
glGenBuffers(1, &global.gVBO);
glBindVertexArray(global.gVAO);
glBindBuffer(GL_ARRAY_BUFFER, global.gVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &global.gIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.gIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
Here i'm basically passing the same structure to both buffers.
Buffers are istantiated in a global struct.
This is MyRenderScene() :
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
global.shaders.enable(); // glUseProgram
global.shaders.set_sampler(0); // setting textures
global.shaders.set_sampler(1);
global.sceneT.set_camera(
global.camera.position(),
global.camera.lookat(),
global.camera.up()
);
glm::mat4 model = glm::mat4(1.0f);
glm::vec3 vaxis = glm::vec3(0.0,1.0,0.0);
glm::vec3 haxis = glm::vec3(1.0,0.0,0.0);
model = glm::rotate(model,glm::radians(global.gradX),haxis);
model = glm::rotate(model,glm::radians(global.gradY),vaxis);
glm::mat4 projection = glm::perspective(glm::radians(40.0f), (float)global.WINDOW_WIDTH/(float)global.WINDOW_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = glm::lookAt(global.camera.position(),global.camera.lookat()+ global.camera.position(),global.camera.up());
global.shaders.set_model(model);
global.shaders.set_view(view);
global.shaders.set_projection(projection);
global.shaders.set_viewPos(global.camera.position());
global.shaders.set_lightPos(lightPos);
global.shaders.update_uniforms();
glBindVertexArray(global.VAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
glBindBuffer(GL_ARRAY_BUFFER, global.VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.IBO);
global.brickwall.Bind(GL_TEXTURE0+0); // binding textures
global.brickwall_normals.Bind(GL_TEXTURE0+1);
glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
global.geometryShader.enable(); // setting up geometry shader
global.geometryShader.set_projection(projection);
global.geometryShader.set_model(model);
global.geometryShader.set_view(view);
global.geometryShader.update_uniforms();
glBindVertexArray(global.gVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, position)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, textcoord)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, normal)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<GLvoid*>(offsetof(struct Vertex, tangent)));
glBindBuffer(GL_ARRAY_BUFFER, global.gVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, global.gIBO);
glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glutSwapBuffers();
glutPostRedisplay();***
I even tried calling the same vertexArrays and vertexArrayBuffer but i get the same result.
Here are vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 textcoord;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec3 tangent;
out VS_OUT {
vec3 newNormal;
} vs_out;
uniform mat4 view;
uniform mat4 model;
void main() {
mat3 normalMatrix = mat3(transpose(inverse(view * model)));
newNormal = vec3(vec4(normalMatrix * normal, 0.0));
gl_Position = view * model * vec4(position, 1.0);
}
And geometryShader:
#version 330 core
layout (triangles) in;
layout (line_strip, max_vertices = 6) out;
in VS_OUT {
vec3 newNormal;
} gs_in[];
const float MAGNITUDE = 0.2;
uniform mat4 projection;
void GenerateLine(int index) {
gl_Position = projection * gl_in[index].gl_Position;
EmitVertex();
gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].newNormal,0.0) * MAGNITUDE);
EmitVertex();
EndPrimitive();
}
void main() {
GenerateLine(0); // first vertex normal
GenerateLine(1); // second vertex normal
GenerateLine(2); // third vertex normal
}
Feel free to correct me on everything possible and imaginable.
The reason for the issue is, that the shader program with the geometry shader fails to compile or link. Hence the geometry is drawn by the default shader program instead of the program with the geometry shader.
There is (at least) one error in the vertex shader:
newNormal = vec3(vec4(normalMatrix * normal, 0.0));
vs_out.newNormal = vec3(vec4(normalMatrix * normal, 0.0));
I am trying to send a single unsigned int to vbo, but when I test its value in the vertex shader (which should be 1), the value is different from the one expected.
The variable that contains my unsigned ints is textureIds
The code that load the vbo :
std::vector<unsigned int> textureIds;
glGenBuffers(1, &vboID_m);
glBindBuffer(GL_ARRAY_BUFFER, vboID_m);
{
glBufferData(GL_ARRAY_BUFFER,
(vertices.size() + texture.size() + normals.size())
* sizeof(float) + textureIds.size() * sizeof(unsigned int), 0,
GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float),
vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float),
texture.size() * sizeof(float), texture.data());
glBufferSubData(GL_ARRAY_BUFFER,
(vertices.size() + texture.size()) * sizeof(float),
normals.size() * sizeof(float), normals.data());
glBufferSubData(GL_ARRAY_BUFFER,
(vertices.size() + texture.size() + normals.size()) * sizeof(float),
textureIds.size() * sizeof(unsigned int), textureIds.data());
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
The code that draw the vbo:
void Chunck::draw() const {
glBindBuffer(GL_ARRAY_BUFFER, vboID_m);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),
BUFFER_OFFSET(verticeSize_m * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
BUFFER_OFFSET(
(verticeSize_m + textureSize_m) * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(unsigned int),
BUFFER_OFFSET(
(verticeSize_m + textureSize_m + normalSize_m) * sizeof(float)));
glEnableVertexAttribArray(3);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, grassTexture_m.getID());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, dirtTexture_m.getID());
glDrawArrays(GL_TRIANGLES, 0, verticeSize_m / 3);
glBindTexture(GL_TEXTURE_2D, 0);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
The vertex shader:
#version 330 core
in vec3 in_Vertex;
in vec2 in_TexCoord0;
in vec3 in_normal;
in int in_textureId;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;
out vec2 coordTexture;
out vec3 normal;
out vec3 FragPos;
out vec3 rayDir;
out float grassAmount;
out float dirtAmount;
void main()
{
vec4 pos = model * vec4(in_Vertex, 1.0);
vec2 mu = vec2(0., 0.);
//pos.y = max(pos.y, 10 * exp(-((pos.x - mu.x) * (pos.x - mu.x) + (pos.z - mu.y) * (pos.z - mu.y)) / 100.));
gl_Position = projection * view * pos;
FragPos = vec3(pos);
coordTexture = in_TexCoord0;
normal = in_normal;
rayDir = (view * model * vec4(FragPos, 1.)).xyz;
grassAmount = 0;
dirtAmount = 0;
if (in_textureId == 0)
grassAmount = 1;
else if (in_textureId == 1)
dirtAmount = 1;
}
I should enter into the second if, but it doesn't :\
You have to use glVertexAttribIPointer (focus on I), when defining the array of generic vertex attribute data, for the vertex attribute in int in_textureId;.
Vertex attribute data defined by glVertexAttribPointer will be converted to floating point.
See OpenGL 4.6 API Core Profile Specification; 10.2. CURRENT VERTEX ATTRIBUTE VALUES; page 344
The VertexAttribI* commands specify signed or unsigned fixed-point values
that are stored as signed or unsigned integers, respectively. Such values are referred to as pure integers.
...
All other VertexAttrib* commands specify values that are converted directly to the internal floating-point representation.
Note, you should use either Layout Qualifier to specify the attribute index in the vertex shader:
layout(location = 0) in vec3 in_Vertex;
layout(location = 1) in vec2 in_TexCoord0;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in int in_textureId;
or you should ask for the attribute index by glGetAttribLocation aftet the program has been linked:
e.g.:
GLuint progObj = ...;
glLinkProgram( progObj );
GLint texIdInx = glGetAttribLocation( progObj, "in_textureId" );
glVertexAttribIPointer(
texIdInx, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(unsigned int),
BUFFER_OFFSET((verticeSize_m + textureSize_m + normalSize_m) * sizeof(float)));
glEnableVertexAttribArray(texIdInx );
Edit:
Of course, glBindAttribLocation is a proper solution too.
Im fairly new to OpenGL and I'm trying to use instancing to draw many 3D rectangles. I have currently positioned each 3d rectangle in a different position and they show properly.
Problem: I now want each 3d rectangle to have a different rotation, defined by me and pass it to the vertex shader. However when I do that, The rectangles do not appear on the screen anymore.
I'm not providing the complete code because it is fairly long. I'm only providing the important part and hoping that i'm making a silly mistake somewhere and you can point it out.
Here is the vertex shader:
#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 offset;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in mat4 instanceMatrix;
uniform mat4 view;
uniform mat4 projection;
out vec2 TexCoord;
void main()
{
TexCoord = texCoord;
gl_Position = projection * view * instanceMatrix * vec4(position + offset, 1.0f) ;
}
Here is the fragment shader:
#version 410 core
out vec4 color;
void main()
{
color = vec4(1.0f,1.0f,1.0f, 1.0f);
}
Here is the C++ code from where im sending the data:
// definition of models variable : std::vector<glm::mat4> models(0);
// Sending the Model matrix for each Rectangle
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), &models[0], GL_STATIC_DRAW);
GLsizei vec4Size = sizeof(glm::vec4);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(vec4Size));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(2 * vec4Size));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(3 * vec4Size));
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);
// unfocus
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I've uploaded vertices, colors, normals, and texture coordinates into a single VBO, which is associated with a VAO. I also have an EBO associated with the same VAO that stores indices. I am also using SDL and OpenGL 3.3 (Core Profile context, which is set using SDL).
At first, my model seems to render fine. Then after maybe 8 or so seconds, it looks like the data gets corrupted.
Here is a video: https://youtu.be/eEiH3EFTPFk
Every frame I am pulling the data out of OpenGL (using glGetNamedBufferSubData) and comparing to what it should be, and everything seems to check out.
Does anyone have any idea what might be happening here? I appreciate any insight you guys might be able to provide.
Here is my code for loading the model data:
struct Vbo
{
GLuint id;
};
struct Ebo
{
GLuint id;
GLenum mode;
GLsizei count;
GLenum type;
};
struct Vao
{
GLuint id;
Vbo vbo[4];
Ebo ebo;
};
// ...
MeshId GraphicsEngine::createStaticMesh(
std::vector<glm::vec3> vertices,
std::vector<glm::detail::uint32> indices,
std::vector<glm::vec4> colors,
std::vector<glm::vec3> normals,
std::vector<glm::vec2> textureCoordinates
)
{
Vao vao;
glGenVertexArrays(1, &vao.id);
glGenBuffers(1, &vao.vbo[0].id);
glGenBuffers(1, &vao.ebo.id);
auto size = vertices.size() * sizeof(glm::vec3);
size += colors.size() * sizeof(glm::vec4);
size += normals.size() * sizeof(glm::vec3);
size += textureCoordinates.size() * sizeof(glm::vec2);
glBindVertexArray(vao.id);
glBindBuffer(GL_ARRAY_BUFFER, vao.vbo[0].id);
glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
auto offset = 0;
glBufferSubData(GL_ARRAY_BUFFER, offset, vertices.size() * sizeof(glm::vec3), &vertices[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
offset += vertices.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, colors.size() * sizeof(glm::vec4), &colors[0]);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(1);
offset += colors.size() * sizeof(glm::vec4);
glBufferSubData(GL_ARRAY_BUFFER, offset, normals.size() * sizeof(glm::vec3), &normals[0]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(2);
offset += normals.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, textureCoordinates.size() * sizeof(glm::vec2), &textureCoordinates[0]);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao.ebo.id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(glm::detail::uint32), &indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
vao.ebo.count = indices.size();
vao.ebo.mode = GL_TRIANGLES;
vao.ebo.type = GL_UNSIGNED_INT;
vertexArrayObjects_.push_back(vao);
auto index = vertexArrayObjects_.size() - 1;
return MeshId(index);
}
Here is my code that does the rendering:
// Setup camera
const glm::quat temp = glm::conjugate(camera_.orientation);
view_ = glm::mat4_cast(temp);
view_ = glm::translate(view_, glm::vec3(-camera_.position.x, -camera_.position.y, -camera_.position.z));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram_);
const int modelMatrixLocation = glGetUniformLocation(shaderProgram_, "modelMatrix");
const int pvmMatrixLocation = glGetUniformLocation(shaderProgram_, "pvmMatrix");
const int normalMatrixLocation = glGetUniformLocation(shaderProgram_, "normalMatrix");
glm::detail::uint32 i = 0;
for ( const auto& r : renderables_ )
{
const auto& graphicsData = graphicsData_[i];
glm::mat4 newModel = glm::translate(model_, graphicsData.position);
newModel = newModel * glm::mat4_cast( graphicsData.orientation );
newModel = glm::scale(newModel, graphicsData.scale);
// Send uniform variable values to the shader
const glm::mat4 pvmMatrix(projection_ * view_ * newModel);
glUniformMatrix4fv(pvmMatrixLocation, 1, GL_FALSE, &pvmMatrix[0][0]);
glm::mat3 normalMatrix = glm::inverse(glm::transpose(glm::mat3(view_ * newModel)));
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, &normalMatrix[0][0]);
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &newModel[0][0]);
glBindTexture(GL_TEXTURE_2D, r.texture.id);
glBindVertexArray(r.vao.id);
glDrawElements(r.vao.ebo.mode, r.vao.ebo.count, r.vao.ebo.type, 0);
glBindVertexArray(0);
i++;
}
Fragment shader:
#version 330 core
in vec4 ourColor;
in vec2 texCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
color = texture(ourTexture, texCoord);
}
Vertex shader:
#version 330 core
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 pvmMatrix;
uniform mat3 normalMatrix;
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec2 textureCoordinate;
out vec4 ourColor;
out vec2 texCoord;
void main()
{
//gl_Position = vec4(position, 1.0);
gl_Position = pvmMatrix * vec4(position, 1.0);
ourColor = color;
texCoord = textureCoordinate;
}
As per #MichaelNastenkos comment about, I added glEnable(GL_DEPTH_TEST); before my rendering code and it seems to fix it.