سؤال

I'm trying to load an image into my game. It's being written in C++, with SDL and OpenGL, and the SDL_Image framework. I've gotten the image in, and have rotated/inverted it to my needs, but there are two main problems.

Firstly, the image's colors are completely inverted. (ie blue -> red) I have the format to either 'GL_RGB' or 'GL_RGBA,' depending on the bytes per pixel. I've tried with PNGs, JPEGs, and BMPs, but their all the same. I'm lost! --Thanks to datenwolf for correcting my silly mistakes!

Secondly, the image draws once, and that's it. It doesn't get redrawn on the other buffer, it just gets displayed once and then is gone as soon as the next frame is drawn.

GLuint loadTexture()
{
SDL_Surface* image = IMG_Load( "/Users/<My name>/Pictures/pacman board.jpeg" );

SDL_DisplayFormatAlpha(image);

unsigned object(0);

glGenTextures(1, &object);

glBindTexture(GL_TEXTURE_2D, object);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


int Mode = NULL;

if(image->format->BytesPerPixel == 3) {Mode = GL_RGB;}
else if(image->format->BytesPerPixel == 4) {Mode = GL_RGBA;}

glTexImage2D(GL_TEXTURE_2D, 0, Mode, image->w, image->h, 0, Mode, GL_UNSIGNED_BYTE, image->pixels);

SDL_FreeSurface(image);
return object;
}

int main(int argc, char * argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_WM_SetCaption("HI", NULL);
SDL_SetVideoMode(600, 600, 32, SDL_OPENGL);

glClearColor(0,0,0,1);
glViewport(0, 0, 600, 600);

glShadeModel(GL_SMOOTH);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

unsigned int pad_texture = 0;
pad_texture = loadTexture();


//---MAIN LOOP---\\

bool isRunning = true;
SDL_Event event;
while (isRunning)
{
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_QUIT) { isRunning = false; }
        if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {isRunning = false;}   
    }


    glClear(GL_COLOR_BUFFER_BIT);
    gluOrtho2D(0, 600, 0, 600); // For some reason, I prefer having '0,0' at the bottom left.

    glPushMatrix();

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,pad_texture);

    glBegin(GL_QUADS);

    glTexCoord2d(0, 1); glVertex2f(0, 0);
    glTexCoord2d(1, 1); glVertex2f(600, 0);
    glTexCoord2d(1, 0); glVertex2f(600, 600);
    glTexCoord2d(0, 0); glVertex2f(0, 600);
    glEnd();

    glDisable(GL_TEXTURE_2D);

    glPopMatrix(); //Stop drawing

    SDL_GL_SwapBuffers();   
}
SDL_Quit();    
return 0;
}
هل كانت مفيدة؟

المحلول

Most image file formats have the pixel data in BGR or BGRA order. If you load such image data using a RGB ordering the blue and red channel will be swapped, of course.

OpenGL does offer those pixel formats as well, since version 1.4. You'll have to either use a extension wrapper like GLEW or fetch and install a current glext.h to get access to the new format tokens. Have a look at http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml for the complete list of supported formats in OpenGL-3 core and later. For older OpenGL, namely OpenGL-1.4 to OpenGL-2.1 look at http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage2D.xml

Update

That your image shows only once is due to the following:

while (isRunning)
{
    /*...*/

    glClear(GL_COLOR_BUFFER_BIT);
    gluOrtho2D(0, 600, 0, 600); // For some reason, I prefer having '0,0' at the bottom left.

gluOrtho2D multiplies on top whats already on the matrix. Which is what gluOrtho2D did in the previous iteration. Also you left the matrix mode in a "dangling" state. As a general rule you should always freshly setup the whole OpenGL drawing state (viewport, clear color, clear depth, all the matrices) at the beginning of each drawing iteration. In your case

while (isRunning)
{
    /*...*/

    glViewport(0, 0, win_width, win_height);

    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, win_width, 0, win_height, -1, 1); // gluOrtho2D is the most useless wrapper ever..., just put a -1, 1 as additional parameters to glOrtho

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glShadeModel(GL_SMOOTH);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top