纹理未正确加载 OpenGL

Texture isn't loading properly OpenGL

我正在使用 MS visual studio 2019,并且刚刚在 C++ 中学习 opengl。我从 https://learnopengl.com 开始学习,它展示了很多加载纹理的方法。我只是使用 stb 图像加载纹理,这里是加载纹理的函数:

 
static unsigned int loadTexture(char const* path)
{
    unsigned int textureID;
    glGenTextures(1, &textureID);

    int width, height, nrComponents;
    unsigned char* data = stbi_load(path, &width, &height, &nrComponents, 0);
    if (data)
    {
        GLenum format;
        if (nrComponents == 1)
            format = GL_RED;
        else if (nrComponents == 3)
            format = GL_RGB;
        else if (nrComponents == 4)
            format = GL_RGBA;

        glBindTexture(GL_TEXTURE_2D, textureID);
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        stbi_image_free(data);
    }
    else
    {
        std::cout << "Texture failed to load at path: " << path << std::endl;
        stbi_image_free(data);
    }

    return textureID;
}

我尝试将它加载到一个矩形中,但不知怎么的,它似乎无法在其上正确打印。我被困了几个小时,仍然找不到我犯了什么错误。 这是初始化 VAO 和 VBO 的代码:

    inline void InitTextureBuffer(const char* img_filepath)
    {
        texture_shader.Bind();
        tex_img_id = loadTexture(img_filepath);
        glGenVertexArrays(1, &tex_VAO);
        glGenBuffers(1, &tex_VBO);
        glBindVertexArray(tex_VAO);
        glBindBuffer(GL_ARRAY_BUFFER, tex_VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
        texture_shader.Unbind();
    }

绘制矩形的函数:

    inline void Draw_Rectangle_IMG(_Point _min, _Point _max)
    {
        glActiveTexture(GL_TEXTURE0);
        glBindVertexArray(tex_VAO);
        texture_shader.Bind();
        float vertices[] =
        {
             _min.x, _min.y,   0.0f, 0.0f ,
             _max.x, _min.y,   0.0f, 1.0f ,
             _max.x, _max.y,   1.0f, 1.0f ,

             _min.x, _min.y,   0.0f, 0.0f ,
             _max.x, _max.y,   1.0f, 1.0f ,
             _min.x, _max.y,   1.0f, 0.0f ,
        };
        glBindTexture(GL_TEXTURE_2D, tex_img_id);

        glBindBuffer(GL_ARRAY_BUFFER, tex_VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDrawArrays(GL_TRIANGLES, 0, 6);

        glBindVertexArray(0);
        glBindTexture(GL_TEXTURE_2D, 0);
        texture_shader.Unbind();
    }

我用过的着色器:

const std::string texture_shader_vs =
{
    "#version 330 core\n"
    "layout(location = 0) in vec2 aPos;\n"
    "layout(location = 1) in vec2 aTexCoord;\n"
    "\n"
    "out vec2 TexCoord;\n"
    "\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos,0.0f, 1.0f);\n"
    "   TexCoord = aTexCoord;\n"
    "}\n"
};
const std::string texture_shader_fs =
{
    "#version 330 core\n"
    "out vec4 FragColor;\n"
    "\n"
    "in vec2 TexCoord;\n"
    "\n"
    "// texture sampler\n"
    "uniform sampler2D texture1;\n"
    "\n"
    "void main()\n"
    "{\n"
    "   FragColor = texture(texture1, TexCoord);\n"
    "}\n"
};

以及我调用的函数:

    _Point p1, p2;
    p1 = _Point(-0.5f, -0.25f);
    p2 = _Point(0.5f, 0.25f);

    ogl.InitTextureBuffer("resources/textures/1.png");
    while (!glfwWindowShouldClose(ogl.GetWindow()))
    {
        glClear(GL_COLOR_BUFFER_BIT);

        ogl.Draw_Rectangle_IMG(p1, p2);

        glfwSwapBuffers(ogl.GetWindow());
        glfwPollEvents();
    }

我尝试打印的纹理是:

但我得到的结果是

我似乎找不到错误。任何帮助将不胜感激。谢谢!

纹理坐标与顶点的关联是错误的。更改为:

float vertices[] =
{
    _min.x, _min.y,   0.0f, 1.0f,
    _max.x, _min.y,   1.0f, 1.0f,
    _max.x, _max.y,   1.0f, 0.0f,

    _min.x, _min.y,   0.0f, 1.0f,
    _max.x, _max.y,   1.0f, 0.0f,
    _min.x, _max.y,   0.0f, 0.0f,
};

默认情况下,OpenGL 假定图像的每一行的开头对齐到 4 个字节。
这是因为 GL_UNPACK_ALIGNMENT 参数默认为 4。当具有 3 个颜色通道的 RGB 图像加载到纹理对象并且 3*width 不能被 4 整除时,这可能会导致未对齐。

在使用 glTexImage2D 指定纹理图像之前,通过将 GL_UNPACK_ALIGNMENT 设置为 1 来更改对齐方式:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);

当您删除 glGenerateMipmap(GL_TEXTURE_2D); 时,您还必须更改缩小功能 (GL_TEXTURE_MIN_FILTER)。由于过滤器是 GL_LINEAR_MIPMAP_LINEAR,如果您不将最小化功能更改为 GL_NEARESTGL_LINEAR.

,则纹理将是“Mipmap Incomplete”