Search code examples
c++opengltexturesglm-mathglew

Problem with rendering a texture as it shows as completely black


I am having trouble with rendering a sprite despite having copied the code from learnopengl in practice section. First I thought that nothing rendered at all, but after changing from black to sort of teal color I found out that the texture was in fact generated but it was a pitch black rectangle and not an annoying open smile of the so called "awesome face" bathed in this well-known computer green.

I tried and tried to search for a solution online. I'm using the unholy abominable combination of glew and SDL, so here's the stupid code:

SPRITE

#pragma once

#include "shader.h"


class skin2D
{

    
public:
    unsigned int ID;

    unsigned int Width, Height;

    unsigned int Internal_Format;
    unsigned int Image_Format;
    unsigned int Wrap_S;
    unsigned int Wrap_T;
    unsigned int Filter_Min;
    unsigned int Filter_Max;
  
   
    skin2D()
    {
        glGenTextures(1, &this->ID);
    }
    void Generate(unsigned int width, unsigned int height, unsigned char* data)
    {
        this->Width = width;
        this->Height = height;
        
        glBindTexture(GL_TEXTURE_2D, this->ID);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
      
        glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data);
        
      
        glBindTexture(GL_TEXTURE_2D, 0);

    }
    
    void Bind() const
    {
        glBindTexture(GL_TEXTURE_2D, this->ID);
    }
};
#include "resouces.h"

std::map<std::string, shader> ResourceManager::Shaders;
std::map<std::string, skin2D> ResourceManager::Textures;

skin2D ResourceManager::loadTextureFromFile(const char* file, bool alpha)
{
  
    // create texture object
    skin2D texture;
    if (alpha)
    {
        texture.Internal_Format = GL_RGBA;
        texture.Image_Format = GL_RGBA;
    }
    // load image
    int width, height, nrChannels;
    unsigned char* data = stbi_load(file, &width, &height, &nrChannels, 0);
    // now generate texture
    texture.Generate(width, height, data);
    // and finally free image data
    stbi_image_free(data);
    return texture;
}

skin2D& ResourceManager::GetTexture(std::string name)
{
   skin2D& skin = Textures[name];
   return skin;
}

Solution

  • If you are not generating mipmaps (with glGenerateMipmap) it is important to set GL_TEXTURE_MIN_FILTER. Since the default filter is GL_NEAREST_MIPMAP_LINEAR, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST or GL_LINEAR.

    The Wrap_S, Wrap_T, Filter_Min and Filter_Max attributes of the Texture object (class skin2D) are never set. I suggest to set the attributes with appropriate defaults:

    class skin2D
    {
    public:
        unsigned int ID = 0;
        unsigned int Width = 0,
        unsigned int Height = 0;
        unsigned int Internal_Format = GL_RGBA;
        unsigned int Image_Format = GL_RGBA;
        unsigned int Wrap_S = GL_REPEAT;
        unsigned int Wrap_T = GL_REPEAT;
        unsigned int Filter_Min = GL_LINEAR_MIPMAP_LINEAR;
        unsigned int Filter_Max = GL_LINEAR;
      
        skin2D()
        {
            glGenTextures(1, &this->ID);
        }
    
        void Generate(unsigned int width, unsigned int height, unsigned char* data)
        {
            this->Width = width;
            this->Height = height;   
            glBindTexture(GL_TEXTURE_2D, this->ID);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
            glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data); 
            glBindTexture(GL_TEXTURE_2D, 0);
        }
    
        // [...]