OpenGL c ++纹理有错误的颜色和位置

时间:2014-07-23 12:52:46

标签: c++ opengl

我有一个使用assimp库从obj文件加载的场景。我按照教程进行操作。它的工作原理,但纹理与原始颜色相比有不同的颜色,它们似乎都在顶部翻转。图像都是tga(我也想摆脱所有的别名)

这是结果

enter image description here

窗帘应该是红色的

enter image description here

我使用freeImage

以这种方式加载纹理
bool Texture::Load(){
    FIBITMAP* bitmap = FreeImage_Load(
        FreeImage_GetFileType(m_fileName.c_str(), 0),
        m_fileName.c_str());
    FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap);
    int nWidth = FreeImage_GetWidth(pImage);
    int nHeight = FreeImage_GetHeight(pImage);
    glGenTextures(1, &m_textureObj);
    glBindTexture(m_textureTarget, m_textureObj);
    glTexImage2D(m_textureTarget, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
    glTexParameterf(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    FreeImage_Unload(pImage);
    return true;
}

使用assimp加载场景并以这种方式处理

void Mesh::InitMesh(const aiMesh* paiMesh,
vector<Vector3f>& Positions,
vector<Vector3f>& Normals,
vector<Vector2f>& TexCoords,
vector<unsigned int>& Indices){

const aiVector3D Zero3D(0.0f, 0.0f, 0.0f);
aiMatrix4x4 Scale(0.3f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.3f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.3f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f);
// Populate the vertex attribute vectors

for (unsigned int i = 0; i < paiMesh->mNumVertices; i++) {
    if (paiMesh->mVertices[i].x < lowX) lowX = paiMesh->mVertices[i].x;
    if (paiMesh->mVertices[i].x > highX) highX = paiMesh->mVertices[i].x;
    if (paiMesh->mVertices[i].y < lowY) lowY = paiMesh->mVertices[i].y;
    if (paiMesh->mVertices[i].y > highY) highY = paiMesh->mVertices[i].y;
    if (paiMesh->mVertices[i].z < lowZ) lowZ = paiMesh->mVertices[i].z;
    if (paiMesh->mVertices[i].z > highZ) highZ = paiMesh->mVertices[i].z;

    //paiMesh->mVertices[i] = Scale*paiMesh->mVertices[i];
    const aiVector3D* pPos = &(paiMesh->mVertices[i]);
    const aiVector3D* pNormal = &(paiMesh->mNormals[i]);
    const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D;

    Positions.push_back(Vector3f(pPos->x, pPos->y, pPos->z));
    Normals.push_back(Vector3f(pNormal->x, pNormal->y, pNormal->z));
    TexCoords.push_back(Vector2f(pTexCoord->x, pTexCoord->y));
}
bbox[0] = Vector3f(abs(lowX), abs(lowY), abs(lowZ));
bbox[1] = Vector3f(abs(highX), abs(highY), abs(highZ));

// Populate the index buffer
for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {
    const aiFace& Face = paiMesh->mFaces[i];
    assert(Face.mNumIndices == 3);
    Indices.push_back(Face.mIndices[0]);
    Indices.push_back(Face.mIndices[1]);
    Indices.push_back(Face.mIndices[2]);
}

}

这就是我初始化纹理的方法

bool Mesh::InitMaterials(const aiScene* pScene, const string& Filename){

// Extract the directory part from the file name
string::size_type SlashIndex = Filename.find_last_of("/");
string Dir;

if (SlashIndex == string::npos) {
    Dir = ".";
}
else if (SlashIndex == 0) {
    Dir = "/";
}
else {
    Dir = Filename.substr(0, SlashIndex);
}

bool Ret = true;

// Initialize the materials
for (unsigned int i = 0; i < pScene->mNumMaterials; i++) {
    const aiMaterial* pMaterial = pScene->mMaterials[i];

    m_Textures[i] = NULL;

    if (true || pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
        aiString Path;

        if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
            string FullPath = Dir + "/" + Path.data;
            m_Textures[i] = new Texture(GL_TEXTURE_2D, FullPath.c_str());

            if (!m_Textures[i]->Load()) {
                printf("Error loading texture '%s'\n", FullPath.c_str());
                delete m_Textures[i];
                m_Textures[i] = NULL;
                Ret = false;
            }
            else {
                printf("%d - loaded texture '%s'\n", i, FullPath.c_str());
            }
        }
    }
}

return Ret;

}

最后,我以这种方式呈现所有内容

    void Mesh::Render()
{
    glBindVertexArray(m_VAO);
    glActiveTexture(GL_TEXTURE0);

    GLenum oldObj = 0;
    if (m_Textures[m_Entries[0].MaterialIndex]){
        m_Textures[m_Entries[0].MaterialIndex]->Bind(GL_TEXTURE0);
        oldObj = m_Textures[m_Entries[0].MaterialIndex]->m_textureObj;
    }

    vector<GLsizei> numIdx;
    vector<GLint> baseVc;
    vector<void*> idx;
    unsigned int drawCount = 0;

    for (unsigned int i = 0; i < m_Entries.size(); i++) {
        const unsigned int MaterialIndex = m_Entries[i].MaterialIndex;

        assert(MaterialIndex < m_Textures.size());

        drawCount++;
        numIdx.push_back(m_Entries[i].NumIndices);
        baseVc.push_back(m_Entries[i].BaseVertex);
        idx.push_back((void*)(sizeof(unsigned int) * m_Entries[i].BaseIndex));

        if (i == m_Entries.size() - 1){
            glDrawElementsBaseVertex(GL_TRIANGLES,
                m_Entries[i].NumIndices,
                GL_UNSIGNED_INT,
                (void*)(sizeof(unsigned int) * m_Entries[i].BaseIndex),
                m_Entries[i].BaseVertex);
        }else
        if (m_Textures[m_Entries[i + 1].MaterialIndex] && m_Textures[m_Entries[i+1].MaterialIndex]->m_textureObj != oldObj) {
            glMultiDrawElementsBaseVertex(GL_TRIANGLES,
                    &numIdx[0],
                    GL_UNSIGNED_INT,
                    &idx[0],
                    drawCount,
                    &baseVc[0]);
            numIdx.clear();
            baseVc.clear();
            idx.clear();
            m_Textures[m_Entries[i + 1].MaterialIndex]->Bind(GL_TEXTURE0);
            oldObj = m_Textures[m_Entries[i + 1].MaterialIndex]->m_textureObj;
            drawCount = 0;
        }else if (!m_Textures[m_Entries[i].MaterialIndex]){
            glMultiDrawElementsBaseVertex(GL_TRIANGLES,
                &numIdx[0],
                GL_UNSIGNED_INT,
                &idx[0],
                drawCount,
                &baseVc[0]);
        }

    }

    // Make sure the VAO is not changed from the outside    
    glBindVertexArray(0);
}

对于大量代码感到抱歉,但由于我不知道错误在哪里发布了整个内容。所有评论

2 个答案:

答案 0 :(得分:1)

在尝试减小纹理的大小时,我遇到了这样的问题,我把RGBA置于错误的位置。您确实使用了位图纹理,这意味着它们不存储Alpha通道,尝试将它们置于GL_RGB模式(您将在GL_RGBA中发送它们)。

答案 1 :(得分:0)

所以事实证明我必须删除flippedUV并且我必须使用RGBA作为内部格式而BGRA用于其他格式