glTexImage2D 不起作用,但将 FragColor 设置为 vec4(1.0, 0, 0, 1.0) 会给我红色图像

glTexImage2D won't work, but setting FragColor to vec4(1.0, 0, 0, 1.0) gives me red image

我正在尝试使用 OpenGL 的纹理单元将图像写入屏幕。如您所见,我将 0 写入 tex Sampler2D,因为我正在使用第 0 个纹理单元。我还将顶点和纹理作为矩形。我检查了 gl 错误,有 none。我也把 FragColor 改成了 vec4(1.0, 0, 0, 1.0);,我确实看到了一个红色的图像,这说明我的坐标是正确的。

这是我的代码:

    static unsigned char * d = new unsigned char[640*360*4];

    const GLfloat vertices_textures[20] = {
    //vertices            //positions
    -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
    1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
    -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
    1.0f, 1.0f, 0.0f, 1.0f, 0.0f};

    if (this->firstRun)
        {
            int i;
            for (i = 0; i < 640*360*4; ++i)
            {
                d[i] = 255;
            }

            program = std::make_unique<Program>();
            Shader vertexShader(ShaderType::Vertex);
            vertexShader.load_from_string(vertexShaderSource);

            program->attach_shader(vertexShader);

            Shader fragmentShader(ShaderType::Fragment);
            fragmentShader.load_from_string(fragmentShaderSource);
            program->attach_shader(fragmentShader);

            program->link();

            vextexInLocation = glGetAttribLocation(program->get_id(), "aPos");

            textureInLocation = glGetAttribLocation(program->get_id(), "aTexCoord");

            glGenVertexArrays(1, &vertexArrayObject);

            glBindVertexArray(vertexArrayObject);

            glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_textures), vertices_textures, GL_STATIC_DRAW);

            glVertexAttribPointer(vextexInLocation, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
            glEnableVertexAttribArray(vextexInLocation);

            glVertexAttribPointer(textureInLocation, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat)));
            glEnableVertexAttribArray(textureInLocation);


            glActiveTexture(GL_TEXTURE0);
            texLocation = glGetUniformLocation(program->get_id(), "tex");

            program->use();

            glGenTextures(1, &texture_id);

            glBindTexture(GL_TEXTURE_2D, texture_id);

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 640, 360, 0,  GL_RED, GL_UNSIGNED_BYTE, d);

            firstRun = false;
        }

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glUniform1i(texLocation, 0);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture_id);
        glBindVertexArray(vertexArrayObject);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

这是我的着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

#version 330 core
out vec4 FragColor;

in vec2 TexCoord;
uniform sampler2D tex;

void main()
{
    FragColor = texture(tex, TexCoord);
}

您不能 "see" 图像,因为纹理不是完整的 mipmap。

参见 OpenGL 4.6 API Compatibility Profile Specification; 8.17 Texture Completeness; page 306

A texture is said to be complete if all the texture images and texture parameters required to utilize the texture for texture application are consistently defined.

... a texture is complete unless any of the following conditions hold true:

  • The minification filter requires a mipmap (is neither NEAREST nor LINEAR), and the texture is not mipmap complete.

GL_TEXTURE_MIN_FILTER的初始值为GL_NEAREST_MIPMAP_LINEAR。如果您不更改它并且不创建 mipmap,则纹理不是 "complete",也不会是 "shown"。参见 glTexParameter

将缩小过滤器设置为 GL_NEARESTGL_LINEAR

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

或通过glGenerateMipmap(GL_TEXTURE_2D)生成mipmap来解决问题。