OpenGL(核心配置文件)纹理缺失或黑色

OpenGL (core profile) textures are missing or black

我正在使用模型的 .obj 附带的 .mtl 文件中的参考来加载纹理。 为此,我正在使用 Assimp 库。

问题是,如标题所述,模型上没有显示纹理,或者(我不敢相信)它是黑色的。

加载纹理的代码如下:

std::vector<texture> model::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName)
{
    std::vector<texture> textures;

    for (GLuint i = 0; i < mat->GetTextureCount(type); i++)
    {
        aiString str;
        mat->GetTexture(type, i, &str);

        GLboolean skip = false;

        for (GLuint j = 0; j < textures_loaded.size(); j++)
        {
            if (textures_loaded[j].path == str)
            {
                skip = true;
                break;
            }
        }

        if (!skip)
        {
            texture tex;
            tex.id = textureFromFile(str.C_Str(), this->directory);
            tex.type = typeName;
            tex.path = str;
            textures.push_back(tex);
            this->textures_loaded.push_back(tex);
        }
    }

    return textures;
}

GLint model::textureFromFile(const char* path, std::string directory)
{
    //Generate texture ID and load texture data 
    std::string filename = std::string(path);
    filename = directory + '\' + filename;

    GLuint textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);

    int width, height;
    unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);

    std::cout << SOIL_last_result() << std::endl;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);

    //auto e = glGetError();

    // Parameters
    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);

    glBindTexture(GL_TEXTURE_2D, 0);
    SOIL_free_image_data(image);

    return textureID;
}

好的,这两个函数读取 .mtl 的纹理名称并从同一目录加载它们。我已经使用调试器逐步执行了代码,宽度和高度设置正确,图像指针指向字符数组。这让我觉得这部分很好。

进一步返回的纹理结构进入我的网格的构造函数object:

mesh::mesh(std::vector<vertex> vertices, std::vector<GLuint> indices, std::vector<texture> textures)
    : vertices(vertices), textures(textures), indices(indices)
{
    this->setupMesh();
}

在 setupMesh 中,我执行基本属性设置、绑定到缓冲区等。 在渲染循环中,我调用了如下所示的 mesh->draw() 方法:

void mesh::draw(shader* shader)
{
    GLuint tex_diffNumber = 1;
    GLuint tex_specNumber = 1;

    for (GLuint i = 0; i < this->textures.size() ; i++)
    {
        //load target texture
        glActiveTexture(GL_TEXTURE0 + 1);

        std::stringstream sstream;
        std::string number;
        std::string name = this->textures[i].type;

        if (name == TEX_DIFF_NAME) 
            sstream << tex_diffNumber++;
        else if (name == TEX_SPEC_NAME) 
            sstream << tex_specNumber++;

        number = sstream.str();

        glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
        glUniform1i(glGetUniformLocation(shader->shaderProgID, (name + number).c_str()), i);

    }

    //set shininess
    //glUniform1f(glGetUniformLocation(shader->shaderProgID, "material.shininess"), 16.0f);

    //draw
    glBindVertexArray(this->vao);
    glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    //release
    for (GLuint i = 0; i < this->textures.size(); i++)
    {
        glActiveTexture(GL_TEXTURE0 + i);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
}

这里重要的一点(恕我直言)是对统一更新的调用:

glUniform1i(glGetUniformLocation(shader->shaderProgID, (name + number).c_str()), i);

再一次,这里没有问题,如果我输入错误,着色器将无法编译,这是着色器:

#version 330 core

in vec2 TexCoords;
in vec4 customColor;

uniform sampler2D tex_diff1;

void main()
{    
    gl_FragColor = vec4(texture(tex_diff1, TexCoords));
}

名称 "tex_diff1" 是调用 draw() 期间使用的确切成员名称。 此外,我测试了纹理坐标是否良好,我根据 texCoords 的值在片段着色器中输出颜色。结果我得到了彩色模型,这意味着一切都很好。

那么问题来了,少了什么?

知道在哪里挖掘和摇晃什么吗?

PS.

Problem image

Texcoords as color

在 for 循环中,您将活动纹理不断设置为 GL_TEXTURE0 + 1,但您告诉着色器使用纹理单元 i。

很可能你想要这样的东西:

for (GLuint i = 0; i < this->textures.size() ; i++)
{
    glActiveTexture(GL_TEXTURE0 + i);
    glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
    glUniform1i(glGetUniformLocation(shader->shaderProgID, (name + number).c_str()), i);
}

切勿使用

glActiveTexture(GL_TEXTURE0 + i)

Description

glActiveTexture selects which texture unit subsequent texture state calls will affect. The number of texture units an implementation supports is implementation dependent, but must be at least 48.

glActiveTexturetexture unit,用于加载相同类型的纹理,例如仅漫反射通道。

如果你有漫反射贴图和法线贴图,你使用两个单位:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->tex_diffuse[i].id);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, this->tex_normal[i].id);

至于为什么它不起作用,我确定你将它绑定到 0。 如果 i=0,则其

glBindTexture(GL_TEXTURE_2D, 0)

那是解除绑定,你的对象是黑色的。