weird behavior of glVertexAttribPointer - opengl

I'm creating default VAO and one VBO, and bind them.
I'm loading model data to the array of structs vertex_data_t
glBufferData(GL_ARRAY_BUFFER, nvertices * sizeof(vertex_data_t), vertices, GL_STATIC_DRAW);
Then in draw function i do:
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_data_t), (const GLvoid *)offsetof(vertex_data_t, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, sizeof(vertex_data_t), (const GLvoid *)offsetof(vertex_data_t, position));
glBindVertexArray(0);
glDrawArrays(GL_TRIANGLES, 0, nvertices);
I'm getting nice, shaded Suzanne:
http://i.stack.imgur.com/uRjpv.png
However, this is wrong! Last argument of glVertexAttribPointer for normal attribute should be 12 aka (const GLvoid *)offsetof(vertex_data_t, normal), but when I do so my Suzanne is broken:
http://i.stack.imgur.com/zBjTS.png
How is it possible? How does shader know an offset to the normal?
Vertex shader:
attribute vec3 vertex;
attribute vec3 normal;
uniform vec4 ambient_color;
uniform vec4 diffuse_color;
uniform vec3 light_position;
uniform mat3 normal_matrix;
uniform mat4 model_view_matrix;
uniform mat4 model_view_projection_matrix;
varying vec4 varying_color;
void main(void) {
vec4 vertex4 = vec4(vertex.x, vertex.y, vertex.z, 1.0);
vec3 eye_normal = normal_matrix * normal;
vec4 position4 = model_view_matrix * vertex4;
vec3 position3 = position4.xyz / position4.w;
vec3 light_direction = normalize(light_position - position3);
float diffuse = max(0.0, dot(eye_normal, light_direction));
varying_color.rgb = diffuse * diffuse_color.rgb;
varying_color.a = diffuse_color.a;
varying_color += ambient_color;
gl_Position = model_view_projection_matrix * vertex4;
}

I think you miss something like:
glBindAttribLocation(progId, 0, "vertex");
glBindAttribLocation(progId, 1, "normal");

Related

OpenGL instancing displays strange shapes

I'm making a simple game in OpenGL where there is one player and multiple bubbles, all being spheres. Unfortunately, instancing doesn't work as expected and causes some strange effects. I'm new to instancing and can't see what may be causing a problem.
Draw method in player class:
void Player::draw(glm::mat4 ViewMat, GLfloat aspect, glm::vec3 light, GLfloat zoom)
{
bindProgram();
bindBuffers();
glm::mat4 Projection = glm::perspective(zoom, aspect, 0.1f, 100.0f);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * ViewMat * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "MVP"), 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "M"), 1, GL_FALSE, &Model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "V"), 1, GL_FALSE, &ViewMat[0][0]);
glUniform3f(glGetUniformLocation(shaderProgram, "origin"), origin.x, origin.y, origin.z);
glUniform3f(glGetUniformLocation(shaderProgram, "lightPosWorld"), light.x, light.y, light.z);
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size() / 3);
}
Static draw method in bubble class:
void Bubble::drawAll(glm::mat4 ViewMat, GLfloat aspect, glm::vec3 light, GLfloat zoom,
std::vector<Bubble *> allInstances)
{
std::vector<float> origins;
uint count = 0;
for (auto b : allInstances)
{
origins.push_back(b->origin.x);
origins.push_back(b->origin.y);
origins.push_back(b->origin.z);
count++;
}
allInstances[0]->bindProgram();
allInstances[0]->bindBuffers();
glBufferData(GL_ARRAY_BUFFER, origins.size() * sizeof(origins), origins.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, originsBuffer);
glVertexAttribPointer(1, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0 // array buffer offset
);
glm::mat4 Projection = glm::perspective(zoom, aspect, 0.1f, 100.0f);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * ViewMat * Model;
GLuint programID = allInstances[0]->shaderProgram;
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 1);
glUniformMatrix4fv(glGetUniformLocation(programID, "MVP"), 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(glGetUniformLocation(programID, "M"), 1, GL_FALSE, &Model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(programID, "V"), 1, GL_FALSE, &ViewMat[0][0]);
glUniform3f(glGetUniformLocation(programID, "lightPosWorld"), light.x, light.y, light.z);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, allInstances[0]->vertices.size() / 3, count);
}
Player vertex shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 origin;
uniform vec3 lightPosWorld;
uniform vec3 cameraPos;
out vec3 vertexPosWorld;
out vec3 vertexNormal;
out vec3 eyeDirectionCamera;
out vec3 lightDirectionCamera;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace + origin,1);
vertexPosWorld = (M * vec4(vertexPosition_modelspace + origin,1)).xyz;
vertexNormal = normalize(vertexPosWorld - origin);
}
Bubble vertex shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 origin;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 lightPosWorld;
uniform vec3 cameraPos;
out vec3 vertexPosWorld;
out vec3 vertexNormal;
out vec3 eyeDirectionCamera;
out vec3 lightDirectionCamera;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace + origin,1);
vertexPosWorld = (M * vec4(vertexPosition_modelspace + origin,1)).xyz;
vertexNormal = normalize(vertexPosWorld - origin);
}
This is what I get:
Effect
But I wanted to get two bubbles that look exactly like the player (which draws correctly).
There are 2 issues in the code:
sizeof(origins) is a byte size of std::vector but not its underlying type. It should be sizeof(float).
glBindBuffer should be called before modifying the buffer’s data and properties.
It should help:
glBindBuffer(GL_ARRAY_BUFFER, originsBuffer);
glBufferData(GL_ARRAY_BUFFER, origins.size() * sizeof(float), origins.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0 // array buffer offset
);

How i can generate normals in GLSL to apply a lighting to cube?

My cubes looks like:
But I want this
I can achive this result if I specify normals in VAO and send it, but i draw the cubes with EBO
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
//float side = diagonal/qSqrt(3);
unsigned int VBO;
QVector3D vertices[] = {
QVector3D(-0.5f,0.5f,-0.5f),
QVector3D(-0.5f,0.5f,0.5f),
QVector3D(0.5f,0.5f,-0.5f),
QVector3D(0.5f,0.5f,0.5f),
QVector3D(-0.5f,-0.5f,-0.5f),
QVector3D(-0.5f,-0.5f,0.5f),
QVector3D(0.5f,-0.5f,-0.5f),
QVector3D(0.5f,-0.5f,0.5f),
};
unsigned int indices[] = {
0,1,2,
1,2,3,
4,5,6,
5,6,7,
0,1,5,
0,4,5,
2,3,7,
2,6,7,
0,2,6,
0,4,6,
1,5,7,
1,3,7
};
functions->glGenBuffers(1, &EBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices),
indices, GL_STATIC_DRAW);
functions->glGenBuffers(1, &VBO);
additionalFunctions->glGenVertexArrays(1, &VAO);
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, VBO);
functions->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STATIC_DRAW);
functions->glEnableVertexAttribArray(0);
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D),
nullptr);
vertex shader
#version 130
in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
fragment shader
#version 130
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
vec3 result = ambient * objectColor;
FragColor = vec4(lightColor * objectColor, 1.0);
}
So, my question is, is it possible to draw cube with EBO with this 8 verteces and specify this material only with shaders and how i can do it without calculating normals manually in CPU?

OpenGL shader is not getting a value from glVertexAttribPointer()

Although I call glEnableVertexAttribArray and glVertexAttribPointer, my vertex shader cannot seem to access the value (I say value because i am not sure what it is called, Attribute?).
I am confused as I have other values that the vertex shader can access by doing exactly the same thing.
In the following code the Vertex position in attribute position 0 and the Vertex normal in attribute position 1 can be accessed fine by the shader however when I use the Vertex color value in attribute position 2 as the color for my mesh it is black even if set otherwise.
//Vertex Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexPosition));
//Vertex Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexNormal));
//Vertex Colour
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexColor));
Here is the Vertex struct
struct Vertex {
glm::vec3 vertexPosition;
glm::vec3 vertexNormal;
glm::vec3 vertexColor;
glm::vec2 textureCoords;
glm::vec3 vertexTangent;
glm::vec3 vertexBitangent;
Vertex() {}
Vertex(glm::vec3 vertexPosition, glm::vec3 vertexNormal = glm::vec3(0), glm::vec3 vertexColor = glm::vec3(0), glm::vec2 textureCoords = glm::vec2(0)) {
this->vertexPosition = vertexPosition;
this->vertexNormal = vertexNormal;
this->textureCoords = textureCoords;
}
};
Here is the Shader code. If I uncomment the commented line the mesh renders red as expected
#version 330 core
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec3 uLightPosition;
layout(location = 0) in vec3 aVertexPosition;
layout(location = 1) in vec3 aVertexNormal;
layout(location = 2) in vec3 aVertexColor;
out vec3 viewDirection;
out vec3 lightPosition;
out vec3 fragmentPosition;
out vec3 materialColor;
flat out vec3 fragmentNormal;
void main(){
materialColor = aVertexColor;
//materialColor = vec3(0.5, 0, 0);
mat4 modelViewMatrix = uViewMatrix * uModelMatrix;
vec3 viewSpacePosition = (modelViewMatrix * vec4(aVertexPosition, 1)).xyz;
viewDirection = normalize(viewSpacePosition);
vec3 viewSpaceNormal = normalize(modelViewMatrix * vec4(aVertexNormal, 0)).xyz;
fragmentNormal = viewSpaceNormal;
fragmentNormal = aVertexNormal;
lightPosition = uLightPosition;
fragmentPosition = vec3(uModelMatrix * vec4(aVertexPosition, 1.0));
gl_Position = uProjectionMatrix * modelViewMatrix * vec4(aVertexPosition, 1);
}
Even if vertexColor defaults to glm::vec3(1) instead of glm::vec3(0) it is still black. I have checked the values for vertexColor before drawing with the shader and the color is not black.
It looks like you are not setting your vertexColor value in the Vertex constructor.
Vertex(glm::vec3 vertexPosition, glm::vec3 vertexNormal = glm::vec3(0), glm::vec3 vertexColor = glm::vec3(0), glm::vec2 textureCoords = glm::vec2(0)) {
this->vertexPosition = vertexPosition;
this->vertexNormal = vertexNormal;
this->vertexColor = vertexColor;
}

OpenGL - Defining Model Matrix via instanced attribute

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);

OpenGL is drawing the UV map instead of the mesh

I am following a youtube tutorial series for OpenGL development. He has uploaded the code on github. However the downloaded code seems to draw the UV map instead of the mesh itself.
I tried to isolate the problem and I think the problem lies in mesh.cpp. I could be wrong.
Maybe the problem is in the glDrawElementsBaseVertex line since we are not specifying the pointer to the indices array.
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawElementsBaseVertex(GL_TRIANGLES, m_numIndices, GL_UNSIGNED_INT, 0, 0);
glBindVertexArray(0);
}
I have tried swapping the position and texture coordinates but that doesnt seem to work.
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, sizeof(model.positions[0]) * model.positions.size(), &model.positions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, sizeof(model.texCoords[0]) * model.texCoords.size(), &model.texCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
Since I am new to OpenGL I am not able to fix this issue. I have already asked the youtuber and I am yet to get a reply.
My graphics card probably had some compatibility issues with OpenGL 120 so I changed it to 330 and a made a few changes and everything started to work fine. Here are the changes I made.
basicShader.vs
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normal;
out vec2 texCoord0;
out vec3 normal0;
uniform mat4 MVP;
uniform mat4 Normal;
void main()
{
gl_Position = MVP * vec4(position, 1.0);
texCoord0 = texCoord;
normal0 = (Normal * vec4(normal, 0.0)).xyz;
}
basicShader.fs
#version 330
out vec4 color;
in vec2 texCoord0;
in vec3 normal0;
uniform sampler2D sampler;
uniform vec3 lightDirection;
void main()
{
color = texture(sampler, texCoord0) *
clamp(dot(-lightDirection, normal0), 0.0, 1.0);
}