移植到OpenGL 3.3后没有任何渲染

时间:2014-01-12 01:30:21

标签: opengl glsl

我认为我已完成移植我的应用程序以使用GL 3.3和#version 330着色器。 但是,我得到一个黑屏(来自glClear()),但没有看到任何错误。我将尝试通过我的代码进行演练。

这是我的渲染功能:

void render() {
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    applyCameraPerspective();
    glUseProgram(prog);
    setUniforms();

    for (ObjectList::iterator it = objectList.begin(); it != objectList.end(); it++) {
        GLuint usedTexture = glTextureList.find((*it)->getTextureName())->second;
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, usedTexture);
        glUniform1ui(textureLoc, 0);
        (*it)->render();
        //glBindTexture(GL_TEXTURE_2D, 0);
    }

    glPopMatrix();
    frameCount++;
}

usedTexture是GLuint纹理索引。

*它是RenderObject类的一个对象,它的render()函数如下所示:

void render() {
    if (totalTriangleCount > 0) {

        glBindBuffer(GL_ARRAY_BUFFER, vbo);

        //glEnableClientState(GL_VERTEX_ARRAY);
        //glEnableClientState(GL_NORMAL_ARRAY);
        //glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        //glVertexPointer(3, GL_FLOAT, 32, BUFFER_OFFSET(0));
        //glNormalPointer(GL_FLOAT, 32, BUFFER_OFFSET(12));
        //glTexCoordPointer(2, GL_FLOAT, 32, BUFFER_OFFSET(24));

        glDrawArrays(GL_TRIANGLES, 0, totalTriangleCount * 3);

        //glDisableClientState(GL_VERTEX_ARRAY);
        //glDisableClientState(GL_NORMAL_ARRAY);
        //glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
}

你可以在这里看到glXXXPointer() - 被删除的函数和客户端状态切换以使用新版本。当我取消注释它们时,奇怪的是,我会渲染几何体,但看起来像是未插入的纹理坐标。但是,布局限定符(请参阅下面的内容)的要点应该是不再需要这些调用。

对象有一个initToGL() - 事先调用的函数,如下所示:

void initToGL(GLuint positionLoc, GLuint normalLoc, GLuint texCoordLoc) {
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    totalTriangleCount = 0;

    for (FaceList::iterator it = faceList.begin(); it != faceList.end(); it++) {
        totalTriangleCount += (*it)->getTriangleCount();
    }

    // Per triangle: 36 bytes for position, 36 for normal, 24 for texture coordinates (32 per vertex)
    UINT bytesNeeded = 3 * (12 + 12 + 8) * totalTriangleCount;
    glBufferData(GL_ARRAY_BUFFER, bytesNeeded, NULL, GL_STATIC_DRAW_ARB);

    glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(0)); // Position
    glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_TRUE, 32, BUFFER_OFFSET(12)); // Normal
    glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(24)); // Texture coordinates

    GLintptr currentOffset = 0;

    for (FaceList::iterator fIt = faceList.begin(); fIt != faceList.end(); fIt++) {
        std::list<std::vector<UINT>> indicesList = (*fIt)->getTriangleVertexIndices();
        for (std::list<std::vector<UINT>>::iterator triIt = indicesList.begin(); triIt != indicesList.end(); triIt++) {
            // Get Vertex positions
            Vector3f vertex1 = (*fIt)->getVertex(triIt->at(0));
            Vector3f vertex2 = (*fIt)->getVertex(triIt->at(1));
            Vector3f vertex3 = (*fIt)->getVertex(triIt->at(2));

            // Calculate normal; keep in mind these vertices are clockwise!
            Vector3f normal = (vertex3 - vertex1).crossProduct(vertex2 - vertex1).normalize();

            // Get texture coordinates
            Vector2f textureCoordinate1 = (*fIt)->getTextureCoordinates(triIt->at(0));
            Vector2f textureCoordinate2 = (*fIt)->getTextureCoordinates(triIt->at(1));
            Vector2f textureCoordinate3 = (*fIt)->getTextureCoordinates(triIt->at(2));

            // Vertex 1
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &vertex1);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &normal);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 8, (GLvoid*) &textureCoordinate1);
            currentOffset += 8;

            // Vertex 2
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &vertex2);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &normal);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 8, (GLvoid*) &textureCoordinate2);
            currentOffset += 8;

            // Vertex 3
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &vertex3);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 12, (GLvoid*) &normal);
            currentOffset += 12;
            glBufferSubData(GL_ARRAY_BUFFER, currentOffset, 8, (GLvoid*) &textureCoordinate3);
            currentOffset += 8;
        }
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

此处,为此函数提供的参数与从着色器中检索的参数相同(请参见下文)。 这里唯一的变化是增加了对glVertexAttribPointer()的3次调用。

applyCameraPerspective():

void applyCameraPerspective() {
    glRotatef(cam->getPitch(), 1.0f, 0.0f, 0.0f);
    glRotatef(cam->getRoll(), 0.0f, 0.0f, 1.0f);
    glRotatef(cam->getYaw(), 0.0f, 1.0f, 0.0f);
    glTranslatef(-cam->x(), -cam->y(), -cam->z());
}

这仍然依赖于OpenGL的矩阵堆栈。

setUniforms():

void setUniforms() {

    GLfloat m[16];

    glGetFloatv(GL_PROJECTION_MATRIX, &m[0]);
    glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, &m[0]);

    glGetFloatv(GL_MODELVIEW_MATRIX, &m[0]);
    //for (int y = 0; y < 4; y++) {
    //  for (int x = 0; x < 4; x++) {
    //      std::cout << std::showpoint << m[4 * x + y] << std::noshowpoint << "  " ;
    //  }
    //  std::cout << std::endl;
    //}
    glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, &m[0]);

    // Error: GL_NORMAL_MATRIX is not a thing. :-(
    //glGetFloatv(GL_NORMAL_MATRIX, 1, GL_FALSE, &m[0]);

    // HACKHACK: As long as we don't do scale transformations (which we don't) we will be fine doing just this.
    m[12] = 0;
    m[13] = 0;
    m[14] = 0;
    glUniformMatrix4fv(normalMatrixLoc, 1, GL_FALSE, &m[0]);
}

你可以在这里看到我添加了输出来测试模型视图矩阵的正确性。这是预期的。

我加载纹理的代码没有改变。我在上传对象之前执行了加载着色器程序的代码,如下所示:

bool setupShader() {
    bool success = true;

    // Vertex shader
    vs = glCreateShader(GL_VERTEX_SHADER);
    std::string vsString = TextFileReader().readWhole("Shader/basic_fog.vert");
    const char* vsChars = vsString.c_str();
    glShaderSource(vs, 1, &vsChars, NULL);
    std::cout << "Compiling vertex shader." << std::endl;
    glCompileShader(vs);
    success &= printShaderInfo(vs);

    // Fragment shader
    fs = glCreateShader(GL_FRAGMENT_SHADER);
    std::string fsString = TextFileReader().readWhole("Shader/basic_fog.frag");
    const char* fsChars = fsString.c_str();
    glShaderSource(fs, 1, &fsChars, NULL);
    std::cout << "Compiling fragment shader." << std::endl;
    glCompileShader(fs);
    success &= printShaderInfo(fs);

    // Bundle them into a program
    prog = glCreateProgram();
    glAttachShader(prog, vs);
    glAttachShader(prog, fs);

    glBindFragDataLocation(prog, 0, "fragColor");
    glLinkProgram(prog);
    success &= printProgramInfo(prog);

    if (success) {
        // These all are GLuints
        positionLoc = glGetAttribLocation(prog, "position");
        normalLoc = glGetAttribLocation(prog, "normal");
        texCoordLoc = glGetAttribLocation(prog, "texCoordinates");

        projectionMatrixLoc = glGetUniformLocation(prog, "projectionMatrix");
        modelViewMatrixLoc = glGetUniformLocation(prog, "modelViewMatrix");
        normalMatrixLoc = glGetUniformLocation(prog, "normalMatrix");

        textureLoc = glGetUniformLocation(prog, "colorTexture");
    }

    return success;
}

请注意,我从不glBindAttribLocation(),因为我使用布局限定符(见下文)。 对于我使用的以下着色器代码,此函数返回true。

顶点着色器:

#version 330
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 position;
layout(location = 0) out vec3 fragPosition;

layout(location = 1) in vec3 normal;
layout(location = 1) out vec3 fragNormal;

layout(location = 2) in vec2 texCoordinates;
layout(location = 2) out vec2 fragTexCoordinates;

uniform mat4 modelViewMatrix, projectionMatrix, normalMatrix;

void main() {
    fragPosition = (modelViewMatrix * vec4(position, 1)).xyz;
    fragNormal = (normalMatrix * vec4(normal, 1)).xyz;
    fragTexCoordinates = vec2(texCoordinates);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
}

片段着色器:

#version 330
#extension GL_ARB_separate_shader_objects : enable

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 textureCoordinates;

layout(location = 0) out vec4 fragColor;

uniform sampler2D colorTexture;

void main() {
    fragColor = texture2D(colorTexture, textureCoordinates);
}

我尝试将fragColor设置为红色:没有结果。没有一个像素穿过片段着色器。

这是很多代码。我非常感谢有人看一看,特别是关于简单地使用某些功能的问题。

1 个答案:

答案 0 :(得分:4)

您的代码最明显的问题之一是不推荐使用的OpenGL混乱,如固定函数矩阵堆栈和自定义统一等现代功能。像这样的东西:

glGetFloatv(GL_PROJECTION_MATRIX, &m[0]);
glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, &m[0]);

表示您正在使用旧式FFP矩阵函数来计算矩阵,从OpenGL查询并将其反馈为统一。你真的不应该这样做。使用真实的矩阵数学库,如GLM或Eigen。

然后当然glEnableClientState将不适用于现代通用顶点属性。我没有看到对glEnableVertexAttribArray的任何调用,所以如果缺少这些调用,那么注意到它就不足为奇了。