1
\$\begingroup\$

I'm building an OpenGL program that imports and render models wich work quite well. but recently I've been facing a problem with a model(Just one model) that works fine in everything else but my project and I would like to fix it since it can get worse in the future.

Here is the rendered model: OpenGL Rendered Model

As you can see, one side of the body and leg don't get the UVs ok (it happens with diffuse, ambient, specular, emissive ... etc maps so i guess it's the UVs)

So I made a change in the texture to See if the problem was with the program just rendering the wrong side... So I changed it to a shitty Photoshop draw: Shitty Draw

And with that I saw two things.

  • First one is that it's trying to render the right part of the texture for everything(Which doesn't match the texture at all!!!!)

  • Second thing I noticed is that instead of rendering it with points, it do with lines.. So my final guess is that it just select some random point everytime and use it.

Here you can see the result my yourselves: Result of test

Need to say that I use OpenGL 4 and those libs (Glew, SDL2, Glm, Soil2, Assymp)

Here is the code where it load the model (I skip the texture part because I thing that it's not really important here)

PD: Don't pay attention to the part where it store the texture in "usedTextures", it's just to prevent from having copies of the same thing that I implemented recently

Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)
{
    //Allocate memory for each vertex, normal map and texture coordinate
    Vertex vertex;
    vector<GLuint> indices;
    if (mesh->HasPositions()) 
    {
        vertex.vertices = new glm::vec3[mesh->mNumVertices]();
        vertex.normal = new glm::vec3[mesh->mNumVertices]();
        vertex.texCoords = new glm::vec2[mesh->mNumVertices]();
    }

    //Process allocated memory
    for (GLuint i = 0; i < mesh->mNumVertices; i++)
    {
        //Positions
        if (mesh->HasPositions())
            vertex.vertices[i] = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
        //Normals
        if (mesh->HasNormals())
            vertex.normal[i] = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
        // Texture Coordinates
        if (mesh->HasTextureCoords(0))
            vertex.texCoords[i] = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
        else
            vertex.texCoords[i] = glm::vec2(0.0f, 0.0f);

    }

    vector<Texture> textures;
    if (mesh->mMaterialIndex) {
        aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
        for (int i = 1; i < aiTextureType_UNKNOWN; i++) 
        {
            Texture texture = processTexture(material, (aiTextureType)i);
            if (texture.GetLocation() != "")
                textures.push_back(texture);
        }
    }

    return Mesh(vertex, textures, mesh->mNumVertices);
}

Texture Model::processTexture(aiMaterial *mat, aiTextureType type)
{
    //Act like there's only one texture by type of map
    aiString fname;
    mat->GetTexture(type, 0, &fname);
    std::string dir = directory + "\\" + fname.C_Str();

    Texture texture;
    if (mat->GetTextureCount(type) > 0) 
    {
        GLuint id;
        if (!isTexLoaded(dir, &id))
        {
            texture = Texture(dir, type);
            usedTextures.push_back(&texture);
        }
        else {
            texture = Texture(id, type);
        }
        return texture;
    }
    return texture;
}

Here is the Mesh class wich just draw everything (Again, I skipped the Texture part so please tell me if you find it important to add)

struct Vertex
{
    glm::vec3 *vertices, *normal;
    glm::vec2 *texCoords;
};
class Mesh
{
public:
    // Position
    Vertex vertex;
    vector<Texture> textures;
    GLuint indices;

    /*  Functions  */
    // Constructor
    Mesh(){}
    Mesh(Vertex vertex, vector<Texture> textures, unsigned int indices)
    {
        this->vertex = vertex;
        this->textures = textures;
        this->indices = indices;

        // Now that we have all the required data, set the vertex buffers and its attribute pointers.
        this->setupMesh();
    }

    // Render the mesh
    void Draw()
    {
        for (unsigned int i = 0; i < textures.size(); i++)
            textures[i].Set();
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, indices);
    }

private:
    /*  Render data  */
    GLuint VAO, VBO, EBO, TEB;

    /*  Functions    */
    // Initializes all the buffer objects/arrays
    void setupMesh()
    {

        glGenVertexArrays(1, &VAO);
        glBindVertexArray(VAO);

        /* copy mesh data into VBOs */
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, 3 * indices * sizeof(GLfloat), vertex.vertices,
            GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(0);
        delete[]vertex.vertices;

        //GLuint vbo;
        glGenBuffers(1, &EBO);
        glBindBuffer(GL_ARRAY_BUFFER, EBO);
        glBufferData(GL_ARRAY_BUFFER, 3 * indices * sizeof(GLfloat), vertex.normal,
            GL_STATIC_DRAW);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(1);
        delete[]vertex.normal;

        //GLuint vbo;
        glGenBuffers(1, &TEB);
        glBindBuffer(GL_ARRAY_BUFFER, TEB);
        glBufferData(GL_ARRAY_BUFFER, 2 * indices * sizeof(GLfloat), vertex.texCoords,
            GL_STATIC_DRAW);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(2);
        delete[]vertex.texCoords;

    }
};

Don't know if it has been posted before, I've been doing a research for every "texture issue" page that i found but nothing like that.

Any idea of where the problem could be or what can be producing it?

Thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ It looks like some of the UVs are outside of the 0...1 range. If your texture sampling wrap mode is set to Clamp, then these areas will show the closest edge of the texture smeared out, creating striped rows or columns. Can you confirm what wrap mode you're using when sampling your textures? \$\endgroup\$ – DMGregory Jan 5 '18 at 14:17
2
\$\begingroup\$

This has been answered by @DMGregory, I'm just posting it.

My problem was that this specific mesh had some UV points outside the range of the texture(the other part) and whenever OpenGL tried to render it, It just applied the property that I set in the sampling wrap(GL_CLAMP_TO_EDGE), Which was taking the outside points back to the edge of the texture.

I changed it to repeat the texture instead of just taking the points to the edge and it fixed the problem.

Here is the code:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.