C++ - SDL/OpenGL加载的图像颜色被反转

3
我正在尝试将一张图片加载到我的游戏中。游戏是用C++、SDL和OpenGL以及SDL_Image框架编写的。 我已经成功加载了这张图片,并根据我的需要旋转/反转了它,但还存在两个主要问题。
首先,图片的颜色完全被反转了(例如,蓝色变成了红色)。我将格式设置为“GL_RGB”或“GL_RGBA”,具体取决于每像素的字节数。我尝试过PNGs、JPEGs和BMPs格式的图片,但都无法解决问题。
其次,该图片只会绘制一次,并不会在其他缓存中重新绘制,当下一帧绘制时,它就会消失。
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;
}
1个回答

2
大多数图像文件格式的像素数据是按BGR或BGRA顺序排列的。如果使用RGB顺序加载此类图像数据,则蓝色和红色通道将被交换。
自OpenGL 1.4版本以来,OpenGL也提供了这些像素格式。您必须使用扩展包装器(如GLEW)或获取并安装当前的glext.h以访问新的格式标记。请查看http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml以获取OpenGL-3核心及更高版本支持的所有支持格式的完整列表。对于旧版OpenGL,即OpenGL-1.4到OpenGL-2.1,请查看http://www.opengl.org/sdk/docs/man2/xhtml/glTexImage2D.xml 更新
您的图像仅显示一次是由于以下原因:
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 在矩阵上方乘以已有的内容,这也是前一个迭代中 gluOrtho2D 所做的。此外,你将矩阵模式留在“悬空”状态。一般来说,在每个绘图迭代的开始,你应该始终重新设置整个 OpenGL 绘图状态(视口、清除颜色、清除深度、所有矩阵)。在你的情况下:

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);

我之前尝试过将if语句中的格式替换为GL_RGBGL_RGBA,但奇怪的是,我只得到了一个白色正方形,然后另一个问题就把它带走了。 - Matt Reynolds
@TheWalkingCactus:你得到“白色”纹理是因为glTexImage将以无效值错误退出(始终检查glGetError!)。 你正在使用相同的格式令牌用于“内部格式”和“格式”,这适用于GL_RGB(A)。 但是仔细阅读参考资料会发现,对于BGR(A)格式,只有“格式”参数而不是“内部格式”参数必须设置为这种方式。 阅读每个参数中允许的标记集的文档。 “内部格式”告诉OpenGL要在内部使用哪种数据类型和精度。 “格式”告诉它如何排列数据。 - datenwolf
哦,我明白了。太好了!现在纹理加载正常了,但只有一帧。嗯,这是一个开始。再次感谢! - Matt Reynolds
顺便说一下,@datenwolf,我还没有将这个答案标记为“已接受”的唯一原因是我还有另一个问题...所以尽管你的答案非常棒,但我不会立即将其标记为已接受。抱歉:( - Matt Reynolds
@TheWalkingCactus:另一个问题是,因为你犯了典型的新手错误:将投影矩阵设置与绘图代码分开,并且在你的情况下是错误的。让我更新我的答案。 - datenwolf
谢谢,让我试一下,然后告诉你结果如何! - Matt Reynolds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接