4
$\begingroup$

I am basically following this tutorial about diffuse lighting in OpenGL. I did some modifications but the idea is the same, at least that's what I think. However, my fragment shader is not showing any colors. I checked and rechecked my uniform variables and light properties and data is ok on CPU side (don't know how to check on GPU side, though). Here are my shaders where I cannot spot any errors, maybe someone can help me out

VERTEX SHADER

#version 410

in vec4 vposition;
in vec3 vnormal;

uniform mat4 M;
uniform mat4 VP;

out vec4 fcolor;
out vec3 fnormal;

void main()
{
    gl_Position = vposition * M * VP;
    fcolor = vposition + vec4(0.5);
    fnormal = (M * vec4(vnormal, 0.0)).xyz;
}

FRAGMENT SHADER

#version 410

in vec4 fcolor;
in vec3 fnormal;

out vec4 color;

uniform vec3 lightColor;
uniform vec3 lightDirection;
uniform float lightIntensity;

void main()
{
    vec3 N = normalize(fnormal);
    vec3 L = normalize(lightDirection);
    float visibility = clamp(dot(N, L), 0.0, 1.0);
    color = fcolor * vec4(lightColor, 1.0) * lightIntensity * visibility;
    //color = vec4(1.0); Not even this shows model in complete white
}

UPDATE

The buffer for my mesh are created like follows, maybe it helps out detecting the problem

void Mesh::initBuffers()
{
    glGenVertexArrays(1, &m_verticesVao);
    glBindVertexArray(m_verticesVao);

    glGenBuffers(1, &m_positionsVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_positionsVbo);
    glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &m_positions[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);

    glGenBuffers(1, &m_normalsVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_normalsVbo);
    glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &m_normals[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);

    glGenBuffers(1, &m_positionsEbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_positionsEbo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_numIndices * 3 * sizeof(unsigned int), &m_indices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);

    m_initBuffers = true;
}

Commenting all the code related to the normal in shaders results in a correct rendered mesh with colors (or white)

If it helps, you can checkout my code

$\endgroup$
  • $\begingroup$ Commenting all the code related to the normal results in a correct rendered mesh with colors (or white) $\endgroup$ – BRabbit27 Jun 22 '16 at 4:56
  • 1
    $\begingroup$ In one statement in the vertex shader you do a left multiply with the vertex data and in the other you do a right multiply. One of those is probably wrong. $\endgroup$ – ratchet freak Jun 22 '16 at 14:00
  • $\begingroup$ Good catch but still not rendering. I am starting to think that the normals are not being passed to the shader ... somehow. $\endgroup$ – BRabbit27 Jun 22 '16 at 14:06
  • $\begingroup$ I notice you are specifying your vertices as vec3s in the CPP side but use vec4s in the vertex shader. Change "in vec4 position" to "in vec3 position", you may need to convert to vec4 with something like vec4(position, 1); . Also I would perform colour calculations in the pixel shader using a vec3 otherwise you will get lighting in your alpha channel. $\endgroup$ – PaulHK Jun 23 '16 at 5:52
  • $\begingroup$ I changed that, but still not able to see anything. Am I binding the index buffer correctly to the positions and normals of the vertices? $\endgroup$ – BRabbit27 Jun 24 '16 at 16:30
3
$\begingroup$

After checking and rechecking my code over and over again. I finally made it work. The problem was that I was creating the buffers and assigning locations to the position and the normals buffers

// Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
// Normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);

However in the vertex shader I was not setting the locations

#version 410

in vec4 vposition;
in vec3 vnormal;
...

So changing the previous code to

#version 410

layout(location = 0) in vec4 vposition;
layout(location = 1) in vec3 vnormal;

fixed the application. Now, I am not really sure why this works, but I remember reading somewhere that OpenGL assigns locations as it sees best, so maybe in my code the location for the normal was not the same as the enabled vertex attrib array. I let someone more experienced clarify this.

$\endgroup$
  • 1
    $\begingroup$ You can use glGetAttribLocation("vposition"); also to get the location without needing assignment in the shader. Although be careful with that, if your attributes are never referenced in your shader the entire attribute may be optimised away and you won't be able to get its location. $\endgroup$ – PaulHK Jul 14 '16 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.