首页 文章

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

提问于
浏览
0

我使用我的模型的.obj文件中的.mtl文件中的引用加载纹理 . 我正在使用Assimp库来达到这个目的 .

问题是,正如 Headers 中所述,纹理没有出现在模型上或(我无法相信)它是黑色的 .

这是加载纹理的代码:

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并从同一目录加载它们 . 我已经使用调试器逐步完成代码,并且正确设置了宽度和高度,并且图像指针指向字符数组 . 这让我觉得这部分很好 .

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

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

这里重要的一点(imho)是对统一更新的调用:

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

2 回答

  • 0

    在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);
    }
    
  • 2

    永远不要使用

    glActiveTexture(GL_TEXTURE0 + i)
    

    Description

    glActiveTexture选择后续纹理状态调用将影响的纹理单元 . 实现支持的纹理单元的数量取决于实现,但必须至少为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)
    

    那是没有约束力的,你的对象是黑色的 .

相关问题