2

しばらくの間、NeHe チュートリアルを使用して OpenGL の学習を開始しました。これはレッスン 6 のコードです。bmp イメージをロードし、描画中の立方体のテクスチャとして使用する必要があります。しかし、正しく動作せず、立方体が画像をロードする関数は「loadGLTextures」です。誰か助けてくれますか? イメージのビット深度は 24 です。Visual Studio 2010 を使用しています。

#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();
    }

}

これは私が読み込もうとしている画像です。

4

3 に答える 3

1

私はSOILライブラリを使用しています。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 };
于 2012-11-08T21:41:57.600 に答える
0

すべては画像のフォーマットに依存します。マイケルが言っSDL_LoadBMPたように、画像データは変換されません。そのため、どのフラグを渡すべきか確信が持てません。図書館
を利用することをお勧めします。SDL_Imageすべての画像形式を 1 つの特定の形式に変換します。次に、(たとえば)GL_RGBAフラグを使用して、すべてが機能することを確認できます。

于 2012-04-26T09:22:29.273 に答える
0

次のように変更することで、プログラムにテクスチャを生成させることができました (ミラーリングされていましたが)。

        textureImage->h , 0 , GL_RGB , GL_UNSIGNED_BYTE , 

に:

        textureImage->h , 0 , GL_RGBA , GL_UNSIGNED_BYTE , 

残念ながら、そのフィールドを間違えてもエラーは発生しません。画像データが実際よりも大きいことをGLに伝えようとすると、プログラムがクラッシュする可能性がありますが、GL_RGBAの代わりにGL_RGBを渡すと、実際よりも小さいと言う効果があります.

SDL_LoadBMP()は画像データの変換を試みないことに注意してください。そのため、BMP ファイルの形式がプログラムが期待するものであることを確認する必要があります。おそらく GL_RGBA または GL_RGB を使用する必要があります。

于 2012-04-26T09:03:46.123 に答える