0
votes

I've recently been working with C++, SDL, and OpenGL, and I've run into an issue, I'm attempting to construct a automated texture loading system as shown below, but all of my textures are coming up as blank white images, I've tested the GLuints, and they seem to be generating correctly, and I've checked to make sure that the names for the keys in the map are being assigned correctly. Here is the graphics part of my program:

SDL_GLContext Graphics_Handler::context;
SDL_Window * Graphics_Handler::window;
std::vector<struct Graphics_Handler::Surface_Container> surface_list;
unsigned int Graphics_Handler::texture_index = 0;
std::map<std::string, GLuint> Graphics_Handler::textures;

/**
 * Loads an image
*/
struct Graphics_Handler::Surface_Container {
    SDL_Surface * surface;
    std::string name;
};
void Graphics_Handler::Load_Textures() {
    GLuint *textures = new GLuint[surface_list.size()];
    glGenTextures(surface_list.size(), textures);
    for (unsigned int i = 0; i < surface_list.size(); i++) {
        glBindTexture(GL_TEXTURE_2D, textures[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, surface_list[i].surface->format-
>BytesPerPixel, surface_list[i].surface->w, surface_list[i].surface->h, 0, 
GL_RGBA, GL_UNSIGNED_BYTE, surface_list[i].surface->pixels);

        Graphics_Handler::textures[surface_list[i].name] = textures[i];
    }
    glBindTexture(GL_TEXTURE_2D, 0);
}

void Graphics_Handler::Load_Surface(const char * file, std::string name) {
    Graphics_Handler::Surface_Container surf;
    surf.surface = IMG_Load(file);
    surf.name = name;
    if (surf.surface == 0) Game::GameError((std::string)"Error Loading image 
    file: " + (std::string)SDL_GetError());  // display the error
    surface_list.push_back(surf);
 }

/**
* draw a GLuint texture
*/
void Graphics_Handler::Draw_Texture(GLuint texture, float x, float y, float 
width, float height){
    glColor3f(1,1,1); // Sets the vertex color
    glBindTexture(GL_TEXTURE_2D, texture); 
    glBegin(GL_QUADS); // Begin drawing a quadrilateral

    glTexCoord2f(0.0f,0.0f); // Specifies where the vertex is on the image 
    rectangle(0 = left, 0 = top);
    glVertex3f(x, y,0.0f); // Specifies where in space the vertex is
    glTexCoord2f(1.0f,0.0f);
    glVertex3f(width + x,0.0f + y,0.0f);
    glTexCoord2f(1.0f,1.0f);
    glVertex3f(width + x, height + y,0.0f);
    glTexCoord2f(0.0f,1.0f);
    glVertex3f(x,height + y,0.0f);
    glEnd();
}

/*
 * gets a texture from the texture map
*/
GLuint Graphics_Handler::Get_Texture(std::string name){
    return Graphics_Handler::textures[name];
}

/**
 * pretty self exclamatory, determines whether a string has a suffix
 */
bool has_suffix(const std::string &str, const std::string &suffix) {
    return str.size() >= suffix.size() && str.compare(str.size() - 
    suffix.size(), suffix.size(), suffix) == 0;
}

/**
 * gets all of the textures from the specified location and adds them to the 
texture map (Load_Image)
*/
void Graphics_Handler::Load_Texture_Files(std::string location) {
    std::string loc = location;
    DIR *dir; //um... idk
    struct dirent *ent; //pointer to directory
    if ((dir = opendir ("textures")) != NULL) {
        //loop through the file pointers (ent) and stop once they're null
        while ((ent = readdir (dir)) != NULL) {
            if(has_suffix(ent->d_name, ".png")){ //make sure it's an image
                location = loc;
                std::string full_location = location.append(ent->d_name); 
//add the texture directory to the string to the png file and convert it to 
a const char*
                std::string name = ((std::string)ent-
>d_name).erase(((std::string)ent->d_name).length()-4); //remove the .png 
extension from the file name to get the common name
                Graphics_Handler::Load_Surface(full_location.c_str(), name);
            }
        }
        closedir (dir); //no memory leaks ;)
        Graphics_Handler::Load_Textures();
    } else {
        //could not open directory
        Game::GameError("Couldn't load textures!?");
    }
}

/**
 * Draws everything to the screen
 */
void Graphics_Handler::Draw(int x, int y){
    glClear(GL_COLOR_BUFFER_BIT); // clear the screen
    glClearColor(0,0,0,1); // set the clear color
    Draw_Texture(Graphics_Handler::Get_Texture("cat"), 50, 50, 100, 100);
    //loop through all of the entities and draw them

    SDL_GL_SwapWindow(Graphics_Handler::window); // Display the screen
}

I have two textures cat.png, and dirt.png

1

1 Answers

1
votes

textures are coming up as blank white images

Sounds like incomplete textures:

What's wrong with this code?

glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);

The texture won't work because it is incomplete. The default GL_TEXTURE_MIN_FILTER state is GL_NEAREST_MIPMAP_LINEAR. And because OpenGL defines the default GL_TEXTURE_MAX_LEVEL to be 1000, OpenGL will expect there to be mipmap levels defined. Since you have only defined a single mipmap level, OpenGL will consider the texture incomplete until the GL_TEXTURE_MAX_LEVEL is properly set, or the GL_TEXTURE_MIN_FILTER parameter is set to not use mipmaps.

Load some mipmaps or switch GL_TEXTURE_MIN_FILTER to GL_NEAREST or GL_LINEAR.