1
votes

The goal of my program is to render a simple cube illuminated by a light point using GLSL shaders. The problem is that my cube stays in black as if lighting properties are disabled. I've been searching a solution since several hours in vain. I have two buffers (one for position vertices and the other for the normal vertices). These two buffers has been generated by Blender. I used them previously in a basic OpenGL program using Vertex Arrays and it worked perfectly. Now I just want to do the same thing but this time using GLSL shaders.

Here's a part of my C++ code :

static GLfloat LightPosition[4] = {0.0f, 10.0f, 10.0f, 1.0f};
static GLfloat Kd[3] = {0.9f, 0.5f, 0.3f};
static GLfloat Ld[3] = {1.0f, 1.0f, 1.0f};

[...]

tatic GLuint            initShaders(char const *vertShaderSrc, char const *fragShaderSrc)
{
    GLuint              vertShaderID = 0, fragShaderID = 0;

    compileShader(vertShaderID, GL_VERTEX_SHADER, vertShaderSrc);
    compileShader(fragShaderID, GL_FRAGMENT_SHADER, fragShaderSrc);

    GLuint programID = glCreateProgram();

    glAttachShader(programID, vertShaderID);
    glAttachShader(programID, fragShaderID);

    glBindAttribLocation(programID, 0, "VertexPosition");
    glBindAttribLocation(programID, 1, "VertexNormal");

    glUniform3f(glGetUniformLocation(programID, "Kd"), Kd[0], Kd[1], Kd[2]);
    glUniform3f(glGetUniformLocation(programID, "Ld"), Ld[0], Ld[1], Ld[2]);

    glLinkProgram(programID);

    GLint errorLink = 0;
    glGetProgramiv(programID, GL_LINK_STATUS, &errorLink);
    if (errorLink != GL_TRUE)
    {
        GLint sizeError = 0;
        glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &sizeError);
        char *erreur = new char[sizeError + 1];
        glGetShaderInfoLog(programID, sizeError, &sizeError, erreur);
        erreur[sizeError] = '\0';
        std::cout << erreur << std::endl;
        delete[] erreur;
        glDeleteProgram(programID);
    }
    return (programID);
}

int                 main(int ac, char **av)
{
    bool            continuer = true;
    SDL_Event       event;
    GLuint          vboID[2];
    GLuint          textureID = 0;
    GLuint          programID = 0;

    //SDL window initialization

    SDL_Init(SDL_INIT_VIDEO);
    SDL_WM_SetCaption("Test", NULL);
    SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);

    //Viewport initialization

    glViewport(0, 0, WIDTH, HEIGHT);

    //Glew init component

    glewInit();

    //VBO initialization

    initVBO(vboID);

    //Shaders initialization

    programID = initShaders("Box.vert", "Box.frag");

    //Main loop

    while (continuer)
    {
        eventListener(&event, &continuer);

        glClearDepth(1.0f);
        glClearColor(0.13f, 0.12f, 0.13f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(programID);

        //Projection matrix

        glm::mat4 ProjectionMatrix = glm::perspective(45.0f, 500.0f / 500.0f, 0.1f, 100.0f);

        //View matrix

        glm::mat4 ViewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 8.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));

        //Model matrix

        glm::mat4 ModelMatrix = glm::mat4(1.0f);
        ModelMatrix = glm::translate(ModelMatrix, glm::vec3(0.0f, 0.0f, 0.0f));
        ModelMatrix = glm::rotate(ModelMatrix, angle, glm::vec3(1.0f, 1.0f, 1.0f));
        ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, 1.0f));

        //Prepare matrix

        glm::mat4 ModelViewMatrix = ViewMatrix * ModelMatrix;
        glm::mat3 NormalMatrix = glm::mat3(glm::vec3(ModelViewMatrix[0]), glm::vec3(ModelViewMatrix[1]), glm::vec3(ModelViewMatrix[2]));
        glm::mat4 ModelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix;
        glm::vec4 LightPositionVec = ViewMatrix * glm::vec4(LightPosition[0], LightPosition[1], LightPosition[2], LightPosition[3]);

        //Send matrix

        glUniform4f(glGetUniformLocation(programID, "LightPosition"), LightPositionVec[0], LightPositionVec[1], LightPositionVec[2], LightPositionVec[3]);
        glUniformMatrix4fv(glGetUniformLocation(programID, "ProjectionMatrix"), 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
        glUniformMatrix3fv(glGetUniformLocation(programID, "NormalMatrix"), 1, GL_FALSE, glm::value_ptr(NormalMatrix));
        glUniformMatrix4fv(glGetUniformLocation(programID, "ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(ModelViewMatrix));
        glUniformMatrix4fv(glGetUniformLocation(programID, "MVP"), 1, GL_FALSE, glm::value_ptr(ModelViewProjectionMatrix));

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vboID[0]);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(0));
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, vboID[1]);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(0));
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glDrawArrays(GL_TRIANGLES, 0, 36);

        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(0);

        glUseProgram(0);

        angle += 0.010f;

        glFlush();
        SDL_GL_SwapBuffers();
    }

    SDL_Quit();
    return (0);
}

Vertex shader code :

#version 330

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

uniform vec4 LightPosition;
uniform vec3 Kd;
uniform vec3 Ld;

uniform mat4 ProjectionMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 MVP;

out vec3 LightIntensity;

void main()
{
    vec3 tnorm = normalize( NormalMatrix * VertexNormal);
    vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0);
    vec3 s = normalize(vec3(LightPosition - eyeCoords));

    LightIntensity = Ld * Kd * max( dot( s, tnorm ), 0.0 );

    gl_Position = MVP * vec4(VertexPosition,1.0);
}

Fragment shader code :

#version 330

in vec3 LightIntensity;

layout (location = 0) out vec4 FragColor;

void main() {
    FragColor = vec4(LightIntensity, 1.0f);
}

Here's a screen of my application :

enter image description here

As you can seen, lighting properties seem to be disabled. Does anyone can help me?

1

1 Answers

5
votes
glUniform3f(glGetUniformLocation(programID, "Kd"), Kd[0], Kd[1], Kd[2]);
glUniform3f(glGetUniformLocation(programID, "Ld"), Ld[0], Ld[1], Ld[2]);

These two rows are at the wrong location, you cannot do this before the shader is linked and bound. move them down to where all the other glUniform calls are made.

You need to reset your uniforms each time you swap shaders, or look into uniform blocks.