2012-04-26 102 views
1

我已经开始使用NeHe教程学习OpenGL了一会儿。这是第6课的代码。它应该加载一个bmp图像并将其用作我绘制的立方体的纹理。但是,它工作不正常,立方体保持白色。加载图像的函数是“loadGLTextures”。任何人都可以帮忙吗? 我的图像位深度与Visual Studio 2010中使用SDL加载OpenGL纹理

#include <Windows.h> 
#include <stdio.h> 
#include <gl\GL.h> 
#include <gl\GLU.h> 
#include <SDL\SDL.h> 


#pragma comment(lib , "SDL.lib") 
#pragma comment(lib , "SDLmain.lib") 
#pragma comment(lib , "OPENGL32.lib") 
#pragma comment(lib , "glu32.lib") 


//height , width and bit depth 
#define SCREEN_WIDTH 800 
#define SCREEN_HEIGHT 600 
#define SCREEN_BPP 16 

//SDL surface 
SDL_Surface* surface; 

//Texture storage. 
GLuint texture[1]; 

//Quit func. 
void Quit(int returnCode) 
{ 
    SDL_Quit(); 
    exit(returnCode); 
} 

//This function will load a bitmap image. 
bool loadGLTextures(void) 
{ 
    SDL_Surface* textureImage; 
    textureImage = SDL_LoadBMP("123.bmp"); 
    if(!textureImage) 
    { 
     fprintf(stderr , "Couldn't load %s.\n" , "123.bmp"); 
     return false; 
    } 

    else 
    { 
     //Create the texture. 
     glGenTextures(1 , &texture[0]); 

     //Typical texture generation using data from the bitmap. 
     glBindTexture(GL_TEXTURE_2D , texture[0]); 

     //Generate the texture. 
     glTexImage2D(GL_TEXTURE_2D , 0 , 3 , textureImage->w , 
      textureImage->h , 0 , GL_RGB , GL_UNSIGNED_BYTE , 
      textureImage->pixels); 

     //Linear filtering. 
     glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR); 

     //Free up the memory. 
     if(textureImage) 
      SDL_FreeSurface(textureImage); 

     return true; 
    } 

} 

//All of the drawing goes throw this. 
int drawGLScene(void) 
{ 
    static float xrot = 0 , yrot = 0 , zrot = 0; 
    //Clear screen and depth buffer. 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    glTranslatef(0.0f , 0.0f , -5.0f); 
    glRotatef(xrot , 1.0f , 0.0f , 0.0f); 
    glRotatef(yrot , 0.0f , 1.0f , 0.0f); 
    glRotatef(zrot , 0.0f , 0.0f ,1.0f); 

    //Select the texture. 
    glBindTexture(GL_TEXTURE_2D , texture[0]); 

    glBegin(GL_QUADS); 
    //Front: 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , 1.0f); 
    //Bottom right fo the texture and quad. 
    glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , 1.0f); 
    //Top right of the texture and quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f); 
    //Top left of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , 1.0f); 

    //Back: 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f); 
    //Bottom right of the texture and quad. 
    glTexCoord2f(1.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f); 
    //Top right of the texture and the quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f); 
    //Top left of the texture and the quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f); 

    //Top: 
    //Top right of the texture and quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f); 
    //Top left of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f); 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , 1.0f , 1.0f); 
    //Bottom right of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f); 

    //Bottom: 
    //Top left of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , -1.0f , 1.0f); 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f); 
    //Bottom right of the texture and quad. 
    glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f); 
    //Top right of the texture and quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , -1.0f , 1.0f); 

    //Right: 
    //Bottom right of the texture and quad. 
    glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f); 
    //Top right of the texture and quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f); 
    //Top left of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f); 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(1.0f , -1.0f , 1.0f); 

    //Left: 
    //Bottom left of the texture and quad. 
    glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f); 
    //Bottom right of the texture and quad. 
    glTexCoord2f(1.0f , 0.0f); glVertex3f(-1.0f , -1.0f , 1.0f); 
    //Top right of the texture and quad. 
    glTexCoord2f(1.0f , 1.0f); glVertex3f(-1.0f , 1.0f , 1.0f); 
    //Top left of the texture and quad. 
    glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f); 
    glEnd(); 

    SDL_GL_SwapBuffers(); 

    xrot += 0.1; 
    yrot += 0.1; 
    zrot += 0.1; 

    return true; 

} 

//This function will reset our viewport after a windows resize. 
int resizeWindow(int width , int height) 
{ 
    //Height/width ration. 
    float ratio; 

    //Protect against a division by zero. 
    if(height == 0) 
     height = 1; 

    ratio = width/height; 

    //Setup viewport 
    glViewport(0 , 0 , width , height); 

    //Change to the projection matrix and reset it. 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    //set perspective. 
    gluPerspective(45.0f , ratio , 0.1f , 100.0f); 

    //Change to model view matrix and reset it. 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    return true; 
} 

//Toggle fullScreen. 
void toggleFullscreen(SDL_Surface* screen) 
{ 
    int videoFlags = screen->flags; 
    (videoFlags & SDL_FULLSCREEN) == SDL_FULLSCREEN ? videoFlags ^= SDL_FULLSCREEN : videoFlags |= SDL_FULLSCREEN;//NICE!! 
    screen = SDL_SetVideoMode(SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_BPP , videoFlags); 
    resizeWindow(surface->w , surface->h); 
    drawGLScene(); 
} 

//OpenGL initialization. 
int initGL(void) 
{ 
    if(!loadGLTextures()) 
     return false; 

    glShadeModel(GL_SMOOTH); 
    glEnable(GL_TEXTURE_2D); //Enable texture mapping. 
    glClearColor(0.0f , 0.0f , 0.0f , 0.5f); 
    glClearDepth(1.0f); 
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LEQUAL); 
    //Nice perspective. 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST); 
    return true; 
} 

//This func will handle any key inputs. 
void handleKeyPress(SDL_keysym* keysym) 
{ 
    switch(keysym->sym) 
    { 
    case SDLK_ESCAPE: 
      Quit(0); 
      break; 
    case SDLK_F1: 
     toggleFullscreen(surface); 
     break; 
    case SDLK_r: 
     drawGLScene(); 
     break; 
    default: 
     break; 
    } 
    return; 
} 


int main(int argc , char* argv[]) 
{ 
    //Flags to pass to SDL_SetVideoMode : awsome!! ints can be compiled. 
    int videoFlags; 
    //Event 
    SDL_Event event; 
    //Holds information about display. 
    const SDL_VideoInfo* videoInfo; 
    //Is window active? 
    bool isActive = true; 

    //SDL initialization. 
    if(SDL_Init(SDL_INIT_VIDEO) < 0) 
    { 
     fprintf(stderr , "SDL video initialization failed : %s\n" , SDL_GetError()); 
     Quit(1); 
    } 

    //Fetch the video info. 
    videoInfo = SDL_GetVideoInfo(); 

    if(!videoInfo) 
    { 
     fprintf(stderr , "Video query failed : %s\n" , SDL_GetError()); 
     Quit(1); 
    } 

    //Add flags to pass to SDL_SetVideoMode. 
    videoFlags = SDL_OPENGL;    //Enable OpenGL in SDL. 
    videoFlags |= SDL_GL_DOUBLEBUFFER; //Enable double buffering. 
    videoFlags |= SDL_HWPALETTE;   //Store the palette in hardware. 
    videoFlags |= SDL_RESIZABLE;   //Enable window resizing. 

    //This checks to see if surfaces can be stored in hardware. 
    videoInfo->hw_available ? videoFlags |= SDL_HWSURFACE : SDL_SWSURFACE; 

    //This checks if harware blits can be done. 
    if(videoInfo->blit_hw) 
     videoFlags |= SDL_HWACCEL; 

    //Set OpenGL double buffering. 
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER , 1); 

    surface = SDL_SetVideoMode(SCREEN_WIDTH , SCREEN_HEIGHT , 16 , videoFlags); 

    //verify the surface. 
    if(!surface) 
    { 
     fprintf(stderr , "Video mode set failed : %s\n" , SDL_GetError()); 
     Quit(1); 
    } 

    SDL_WM_SetCaption("OpenGL-Sample" , 0); 

    //initialize OpenGL 
    if(initGL() == false) 
    { 
     fprintf(stderr , "Could not initialize OpenGL.\n"); 
     Quit(1); 
    } 

    //Main loop 
    while(1) 
    { 
     //Handle the events in the queue. 
     if(SDL_PollEvent(&event)) 
     { 
      switch(event.type) 
      { 
      case SDL_ACTIVEEVENT: 
       if(event.active.gain == 0) 
        isActive = false; 
       else 
        isActive = true; 
       break; 
      case SDL_VIDEORESIZE: 
       //Handle resize event. 
       surface = SDL_SetVideoMode(event.resize.w , event.resize.h , SCREEN_BPP , videoFlags); 
       if(!surface) 
       { 
        fprintf(stderr , "Could not get a surface after resize : %s\n" , SDL_GetError()); 
        Quit(1); 
       } 
       resizeWindow(event.resize.w , event.resize.h); 
       break; 
      case SDL_KEYDOWN: 
       handleKeyPress(&event.key.keysym); 
       break; 
      case SDL_QUIT: 
       Quit(0); 
      default: 
       break; 
      } 
     } 
     if(isActive) 
      drawGLScene(); 
    } 

} 

工作24.I'm这是image我试图加载。

+0

使用'glGetError'检查无效的条件GL调用之后。 – 2012-04-26 08:49:49

+0

我找到了这个,但它不起作用。 http://content.gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL#How_To_Load_an_OpenGL_Texture_from_an_SDL_Surface – 2012-04-26 08:51:56

回答

0

我能够通过改变让你的程序产生的纹理(虽然它反映):

 textureImage->h , 0 , GL_RGB , GL_UNSIGNED_BYTE , 

到:

 textureImage->h , 0 , GL_RGBA , GL_UNSIGNED_BYTE , 

获得那场错误遗憾的是不产生任何错误。如果您试图告诉GL图像数据比实际大,那么它可能会导致程序崩溃,但传递GL_RGB而不是GL_RGBA会导致它比实际小。

请记住,SDL_LoadBMP()不会尝试转换图像数据,所以您必须确保BMP文件的格式是程序所期望的。您可能需要使用GL_RGBA或GL_RGB。

0

一切都取决于您的图像格式。正如Michael所说的SDL_LoadBMP不会转换图像数据。所以你不能确定你应该通过哪一面旗帜。
我建议您使用SDL_Image库。它将所有图像格式转换为一种特定的格式。然后,您可以使用(例如)GL_RGBA标志并确保一切正常!

+0

SDL_image不工作too.I如果你想检查它,我已经在我的问题的最后添加了图像。 – 2012-04-26 09:48:35

1

我用的是土库,http://www.lonesock.net/soil.html

这是一个非常容易使用的OpenGL纹理加载库,你不必 担心图像格式或作出任何代码加载自己,它会做一切为您。

加载质地,因为这很容易:

int textureID = SOIL_load_OGL_texture("img.png", SOIL_LOAD_AUTO, 
    SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); 
if(textureID == 0) { cout << "Failed to load texture!" << endl };