1

我的程序的目标是使用 GLSL 着色器渲染一个由光点照亮的简单立方体。问题是我的立方体保持黑色,就好像照明属性被禁用一样。几个小时以来,我一直在寻找解决方案。我有两个缓冲区(一个用于位置顶点,另一个用于正常顶点)。这两个缓冲区是由 Blender 生成的。我以前在使用顶点数组的基本 OpenGL 程序中使用它们,它运行良好。现在我只想做同样的事情,但这次使用 GLSL 着色器。

这是我的 C++ 代码的一部分:

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

顶点着色器代码:

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

片段着色器代码:

#version 330

in vec3 LightIntensity;

layout (location = 0) out vec4 FragColor;

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

这是我的应用程序的屏幕:

在此处输入图像描述

如您所见,照明属性似乎被禁用。有人可以帮助我吗?

4

1 回答 1

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

这两行位于错误的位置,在链接和绑定着色器之前不能这样做。将它们移到所有其他 glUniform 调用的位置。

每次交换着色器或查看统一块时,您都需要重置制服。

于 2013-04-08T02:36:43.460 回答