簡體   English   中英

在某些情況下,多個 OpenGL 紋理不起作用?

[英]Multiple OpenGL Textures not working in some instances?

我正在嘗試加載 OBJ 文件以在 OpenGL 中使用它們。 OBJ 文件中的每個對象都有自己的紋理。 在我的代碼中,我將文件的每個對象拆分為一個結構體,如下所示:

struct ObjModelComponent {
    std::vector<glm::vec3> vertices;
    std::vector<glm::vec2> uvs;
    std::vector<glm::vec3> normals;

    Texture tex;
    ArrayBuffer vertex, uv, normal;
    GLuint VAO;
};

Texture類是一個簡單的類,使加載和處理紋理更容易。

在模型的類中,我有一個std::vectorObjModelComponent

我正在像這樣渲染對象:

void ObjModel::render() {
    for(int i = 0; i < components.size(); i++) {
        components[i].vertex.activate();
        components[i].uv.activate();
        components[i].normal.activate();

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, components[i].tex.getTextureID());
        shader->sendInt(0, components[i].tex.getTextureName());

        glBindVertexArray(components[i].VAO);
        shader->sendMat4(*data->projection, "projection");
        shader->sendMat4(data->viewMat, "view");
        shader->sendMat4(model, "model");

        glDrawArrays(GL_TRIANGLES, 0, int(components[i].vertices.size()));
        glBindVertexArray(0);
    }
}

Texture 類看起來像這樣:

Texture::Texture(std::string fileName, TextureType type):
textureName("tex"), fileName(fileName), type(type) {
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    unsigned char *image = SOIL_load_image(fileName.c_str(), &texWidth, &texHeight, 0, SOIL_LOAD_RGBA);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    switch (type) {
        case TEXTURE_GENERATE_MIPMAP:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);

            glGenerateMipmap(GL_TEXTURE_2D);
            break;

        case TEXTURE_NO_MIP_MAP:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        default:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            break;
    }

    glBindTexture(GL_TEXTURE_2D, 0);

    SOIL_free_image_data(image);
}

Texture::Texture() {

}

Texture& Texture::operator=(const Texture &other) {
    this->fileName = other.fileName;
    this->textureName = other.textureName;
    this->type = other.type;

//    glDeleteTextures(1, &tex);

    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    unsigned char *image = SOIL_load_image(fileName.c_str(), &texWidth, &texHeight, 0, SOIL_LOAD_RGBA);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    switch (type) {
        case TEXTURE_GENERATE_MIPMAP:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);

            glGenerateMipmap(GL_TEXTURE_2D);
            break;

        case TEXTURE_NO_MIP_MAP:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        default:
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            break;
    }

    glBindTexture(GL_TEXTURE_2D, 0);

    SOIL_free_image_data(image);

    return *this;
}

Texture::~Texture() {
    glDeleteTextures(1, &tex);
}

GLuint Texture::getTextureID() {
    return tex;
}

void Texture::setTextureName(std::string name) {
    textureName = name;
}

std::string Texture::getTextureName() {
    return textureName;
}

glm::vec2 Texture::getTextureSize() {
    return glm::vec2(texWidth, texHeight);
}

這是組件的生成方式:

    for(int i = 0; i < fileLines.size(); i++) {
            if(fileLines[i].substr(0, 2) == "o ") {
                if(!first) {
                    tmpComp.tex = tmpTex;
                    components.emplace_back(tmpComp);
                    componentIndex++;
                }

                first = false;

                tmpTex = Texture(hg::substr(path, 0, int(path.find_last_of("/"))) + "/" + hg::substr(fileLines[i], 2, int(fileLines[i].length())) + ".png");
            }
    }

這是 VAO 和數組緩沖區的生成方式:

for(int i = 0; i < components.size(); i++) {
        glGenVertexArrays(1, &components[i].VAO);
        glBindVertexArray(components[i].VAO);

        components[i].vertex.setData(components[i].vertices.data(), sizeof(glm::vec3) * components[i].vertices.size(), 0);
        components[i].uv.setData(components[i].uvs.data(), sizeof(glm::vec2) * components[i].uvs.size(), 1);
        components[i].normal.setData(components[i].normals.data(), sizeof(glm::vec3) * components[i].normals.size(), 2);

        components[i].vertex.activate();
        components[i].uv.activate();
        components[i].normal.activate();

        glBindVertexArray(0);
    }

你可以在 GitHub 上找到我的完整代碼: https : //github.com/Kuechenzwiebel/SDL-OpenGL-Tests

問題是,顯示在我的對象上的紋理是最后一個渲染對象使用的紋理。

更新:刪除紋理析構函數中的glDeleteTextures ,結果顯示所有組件上顯示的紋理是用於最后一個組件的紋理。

我真的不明白為什么這不起作用,我從其他原語復制它,只使用一種紋理。 一切正常。

我找到了一種解決方法,而不是使用單獨的 ArrayBuffers 和 VAO,我只使用其中的一個,並存儲新對象開始的索引。 在那里我改變了使用的紋理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM