初始化多个纹理 OpenGL、SDL C++ 时出现问题

Issues with initializing multiple textures OpenGL, SDL, C++

本文关键字:C++ 问题 SDL 纹理 OpenGL 初始化      更新时间:2023-10-16

我最近一直在使用 C++、SDL 和 OpenGL,遇到了一个问题,我正在尝试构建一个如下所示的自动纹理加载系统,但我所有的纹理都显示为空白的白色图像,我已经测试了 GLuint,它们似乎正在正确生成,并且我已经检查以确保映射中键的名称被正确分配。这是我程序的图形部分:

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
}

我有两种纹理猫.png和污垢.png

纹理显示为空白的白色图像

听起来像不完整的纹理:

这段代码有什么问题?

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

纹理不起作用,因为它不完整。默认 GL_TEXTURE_MIN_FILTER状态是GL_NEAREST_MIPMAP_LINEAR .因为 OpenGL将默认GL_TEXTURE_MAX_LEVEL定义为1000,OpenGL 将期望定义 mipmap 级别。既然你只有 定义了单个 mipmap 级别,OpenGL 将考虑纹理 在正确设置GL_TEXTURE_MAX_LEVEL之前不完整,或者 GL_TEXTURE_MIN_FILTER参数设置为不使用 mipmap。

加载一些 mipmap 或将GL_TEXTURE_MIN_FILTER切换到 GL_NEARESTGL_LINEAR