C++ - SDL/OpenGL 加载图像的颜色被反转
Posted
技术标签:
【中文标题】C++ - SDL/OpenGL 加载图像的颜色被反转【英文标题】:C++ - SDL/OpenGL loaded image's colors are inverted 【发布时间】:2013-04-06 16:11:33 【问题描述】:我正在尝试将图像加载到我的游戏中。它是用 C++ 编写的,带有 SDL 和 OpenGL,以及 SDL_Image 框架。 我已经获得了图像,并根据我的需要对其进行了旋转/反转,但是有两个主要问题。
首先,图像的颜色完全反转。 (即蓝色 -> 红色)
我的格式为“GL_RGB”或“GL_RGBA”,具体取决于每个像素的字节数。我尝试过使用 PNG、JPEG 和 BMP,但它们都一样。我迷路了!
--感谢 datenwolf 纠正我的愚蠢错误!
其次,图像绘制一次,仅此而已。它不会在另一个缓冲区上重新绘制,它只会显示一次,然后在绘制下一帧时立即消失。
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】:大多数图像文件格式都有 BGR 或 BGRA 顺序的像素数据。如果您使用 RGB 排序加载此类图像数据,那么蓝色和红色通道当然会交换。
从 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
s 中的格式替换为GL_RGB
和GL_RGBA
,奇怪的是,在其他问题出现之前,我得到的唯一的东西是一个白色方块离开。
@TheWalkingCactus:您会得到“白色”纹理,因为 glTexImage 会因无效值错误而退出(始终检查 glGetError!)。您对internal format
和format
使用相同的格式标记,它适用于GL_RGB(A)。但是仔细阅读参考资料会发现,对于 BGR(A) 格式,只有 format
参数,但不是 internal format
参数必须这样设置。阅读每个参数中允许的标记集的文档。 internal format
告诉 OpenGL 内部使用的数据类型和精度。 format
告诉它,data
是如何排列的。
哦,我明白了。效果很好!现在,纹理正确加载,但仅适用于一帧。哦,好吧,这是一个开始。再次感谢!!
顺便说一句,@datenwolf,我没有将此答案标记为“已接受”的唯一原因是因为我还有其他问题......所以虽然你的答案很惊人,但我不会t 将其标记为已接受(尚未)。对不起:(
@TheWalkingCactus:另一个问题是,因为您犯了经典的新手错误:您将投影矩阵设置与绘图代码分开,而您的情况是错误的。让我更新我的答案。以上是关于C++ - SDL/OpenGL 加载图像的颜色被反转的主要内容,如果未能解决你的问题,请参考以下文章
具有 0 个颜色位和 0 个深度位的 SDL2 OpenGL 4.2 上下文
如何在 C++ 中使用 sdl、opengl 移动相机时修复奇怪的相机旋转
是否可以在 Web 浏览器上运行与 SDL+OpenGL 代码绑定的 C++?