tigeradol
tigeradol

Reputation: 259

OpenGL c++ Textures have wrong colors and position

I have a scene that I load from a obj file using the assimp library. I followed a tutorial in order to do it. It works but textures have different colors compared to the original and they all seem to be flipped top-bottom. The images are all tga (I would also like to get rid of all the aliasing)

here is the result

enter image description here

and the curtain should be red

enter image description here

I load the textures this way using 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;
}

while the scene is loaded using assimp and processed this way

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

}

and this is how I initialise textures

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;

}

In the end I render everything in this way

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

Sorry for the large amount of code but since I don't know where is the error I posted the entire thing. It's all commented

Upvotes: 0

Views: 366

Answers (2)

tigeradol
tigeradol

Reputation: 259

So it turns out that I had to remove flippedUV and i had to use RGBA as internal format and BGRA for the other format

Upvotes: 1

Symeon94
Symeon94

Reputation: 76

I had that kind of issue while trying to reduce the size of the textures, i was puting RGBA in the wrong position. You do use Bitmap textures, which means they dont store an alpha channel, try to put them in GL_RGB mode (you are sending them in GL_RGBA).

Upvotes: 1

Related Questions