0
votes

I've got a little problem with texturing.

I load the mesh via assimp, which works perfectly fine, the model looks the way it should.. but it's black..

So, at first I load the shader and then start to load the mesh, including vertices, faces and uv's for now. To keep it at a minimum, I will only show the texture relevant code.

    texID = glGetUniformLocation(shaderProgram, "myTextureSampler");
    loadScene(modelPath);

loadScene would now import the whole modelscene we get through the modelpath.

So, first part where I don't think it is the problem, but it could be, maybe I missed something, while debugging everything seemed fine. I go for the texture using the FreeImage library.

bool loadGLTextures(const aiScene* scene)
{

    /* unload image first */
    if (pImage) 
    {
        FreeImage_Unload(pImage);
        pImage = 0;
    }

    if (scene->HasTextures()) 
    {
        std::cerr << "Support for meshes with embedded textures is not (yet)
            implemented" << std::endl;
        return false;
    }

    /* getTexture Filenames and Numb of Textures */
    for (unsigned int m=0; m < scene->mNumMaterials; m++)
    {
        int texIndex = 0;
        aiReturn texFound = AI_SUCCESS;

        aiString path;  // filename

        while (texFound == AI_SUCCESS)
        {
            texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE,
                texIndex, &path);
        textureIdMap[path.data] = NULL;
        //fill map with textures, pointers still NULL yet
        texIndex++;
        }
    }

    int numTextures = textureIdMap.size();

    /* create and fill array with GL texture ids */
    textureIds = new GLuint[numTextures];
    glGenTextures(numTextures, textureIds); /* Texture name generation */

    /* get iterator */
    std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();

    for (int i=0; i < numTextures; i++)
    {
        std::string filename = (*itr).first;  // get filename
        (*itr).second = &textureIds[i]; // save texture id for filename in map
        itr++; // next texture

        std::string fileloc = basepath + filename;  /* Loading of image */

        // Check the file signature and deduce its format.  
        FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(fileloc.c_str(), 0);  

        // If still unknown, try to guess the file format from the file extension.  
        if(fif == FIF_UNKNOWN)  
        {  
            fif = FreeImage_GetFIFFromFilename(fileloc.c_str());  
        }  

        // If still unkown, return failure.  
        if(fif == FIF_UNKNOWN)  
        {  
            return false;  
        }  

        // Check that the plugin has reading capabilities and load the file.  
        if(FreeImage_FIFSupportsReading(fif))  
        {  
            pImage = FreeImage_Load(fif, fileloc.c_str());  
        } 

        if (pImage != 0) /* If no error occured: */
        {
            glBindTexture(GL_TEXTURE_2D, textureIds[i]);

            unsigned int width = pImage ? FreeImage_GetWidth(pImage) : 0;
            unsigned int height = pImage ? FreeImage_GetHeight(pImage) : 0;
            const BYTE *bits = pImage ? FreeImage_GetBits(pImage) : 0;

            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_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                GL_LINEAR_MIPMAP_LINEAR); 
            // Initialise texture with image data.  
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
                GL_UNSIGNED_BYTE, bits);
            }
            else
            {
                /* Error occured */
                std::cerr << "Couldn't load image: " + fileloc << std::endl;
            }
        }

    //return success;
    return true;
}

After we got the texture, i go for the mesh(es) but the only part that would be relevant, would be the uv part and the binding, so lets skip to the material loading - as there is no light yet, I kept it at a minimum.

void initMaterial(const aiMaterial* mtl)
{

    int texIndex = 0;
    aiString texPath; //contains filename of texture

    if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
    {
        //bind texture
        GLuint texId = *textureIdMap[texPath.data];
        glBindTexture(GL_TEXTURE_2D, texId);
        glActiveTexture(GL_TEXTURE0);
    }
}

So, the following part would also go for vertices and normals, but they don't really matter for me at the moment, the vertices work, while the texture doesn't...

glUseProgram(shaderProgram);

glUniform1i(texID, 0);

glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

glDisableVertexAttribArray(1);

And for completion, the shaders, they are kept basic for now, just to test texturing.

vertexshader

layout(location = 1) in vec2 vertexUV;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

void main(){

....

    // UV of the vertex. No special space for this one.
    UV = vertexUV;
}

fragmentshader

// Interpolated values from the vertex shaders
in vec2 UV;

// Ouput data
out vec3 color;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;

void main(){

    // Output color = color of the texture at the specified UV
    color = texture2D( myTextureSampler, UV ).rgb;
}

So, that's about it. As I said, I get no error, everything loads fine and is displayed but instead of a texture I only get blackness.

1
Way too much code. Strip it down to just the questionable part. If you don't know what part that is, then you haven't tried enough to debug it yourself first. For example, if you don't know if your shader works, make a simpler test case and test it. If it works, then you don't need to post it here. Wash, rinse, and repeat with the rest of the 3 miles of code here.derpface

1 Answers

4
votes

You specify the GL_LINEAR_MIPMAP_LINEAR minifiaction filter, but your texture is not mipmap complete, since you only specify level 0 (I assume your image is bigger than 1x1 here). There are several options:

  1. Use another filter like GL_LINEAR. This is especially useful as a quick test to see if it starts working then.
  2. Supply the whole set of mipmap leves. Each level has 1/2 of the width and 1/2 of the height of the previous one, until 1x1 is reached.
  3. Let the GL generate the mipmap levels via glGenerateMipmap().