c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?
Posted
技术标签:
【中文标题】c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?【英文标题】:c++: how can i use sdl to load a bitmap into a cube in opengl? 【发布时间】:2010-04-04 02:23:25 【问题描述】:我正在学习 OpenGL 和 SDL,到目前为止,我已经能够正确地绘制和旋转 3d 多边形(对我来说耶!:))
如何使用 SDL 加载图像文件并将纹理加载到我使用 OpenGL 在屏幕上绘制的 3d 形状上。
谢谢!!!
更新
我尝试了以下代码来绘制一个立方体,旋转它并添加一个位图,但我看不到位图可见。有什么想法吗?
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#if defined(__APPLE__) && defined(__MACH__)
#include <OpenGL/gl.h> // Header File For The OpenGL32 Library
#include <OpenGL/glu.h> // Header File For The GLu32 Library
#else
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#endif
#include "SDL.h"
#include <stdio.h>
#include <unistd.h>
SDL_Surface *screen=NULL;
GLfloat rtri; // Angle For The Triangle ( NEW )
GLfloat rquad; // Angle For The Quad ( NEW )
GLuint texture; // This is a handle to our texture object
SDL_Surface *surface; // This surface will tell us the details of the image
GLenum texture_format;
GLint nOfColors;
bool InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
if ( (surface = SDL_LoadBMP("icon.bmp")) )
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 )
printf("error: image.bmp's width is not a power of 2\n");
return false;
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 )
printf("error: image.bmp's height is not a power of 2\n");
return false;
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
else if (nOfColors == 3) // no alpha channel
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
else
printf("error: the image is not truecolor.. this will probably break\n");
return false;
// this error should not go unhandled
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels );
else
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return false;
return true;
/* The main drawing function. */
int DrawGLScene()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glRotatef(rtri,0.0f,1.0f,0.0f); // Rotate The Triangle On The Y axis ( NEW )
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
// Back Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
// Top Face
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
// Right face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glEnd();
rtri+=0.02f; // Increase The Rotation Variable For The Triangle ( NEW )
rquad-=0.015f; // Decrease The Rotation Variable For The Quad ( NEW )
// swap buffers to display, since we're double buffered.
SDL_GL_SwapBuffers();
return true;
int main(int argc,char* argv[])
int done;
/*variable to hold the file name of the image to be loaded
*In real world error handling code would precede this
*/
/* Initialize SDL for video output */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
exit(1);
atexit(SDL_Quit);
/* Create a 640x480 OpenGL screen */
if ( SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL )
fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
SDL_Quit();
exit(2);
SDL_WM_SetCaption("another example",NULL);
InitGL(640,480);
done=0;
while (! done)
DrawGLScene();
SDL_Event event;
while ( SDL_PollEvent(&event) )
if ( event.type == SDL_QUIT )
done = 1;
if ( event.type == SDL_KEYDOWN )
if ( event.key.keysym.sym == SDLK_ESCAPE )
done = 1;
return 1;
【问题讨论】:
【参考方案1】:我使用 sdl 和 opengl,我建议你使用 lib DevIl 来加载图像
这里有一个用 devIl 创建纹理的函数:
ilInit();
iluInit();
GLuint texture;
ILuint texid;
ilGenImages(1, &texid);
ilBindImage(texid);
ilLoadImage("tex.png");
iluFlipImage();
ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), ilGetInteger(IL_IMAGE_FORMAT),
GL_UNSIGNED_BYTE, ilGetData());
ilDeleteImage(texid);
:)
【讨论】:
devil 看起来不错,但是我在雪豹下编译使用恶魔库的脚本时遇到了问题,所以我回到了 SDL。【参考方案2】:我并不是真正的 SDL 人,但这可能会对您有所帮助:http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL#How_To_Load_an_OpenGL_Texture_from_an_SDL_Surface
编辑:我编译了你的代码,这就是你所缺少的:
将glEnable( GL_TEXTURE_2D );
放入您的initGL
函数中。我把它放在glShadeMode(GL_SMOOTH)
之后
确保您的位图是 24 位的(我尝试了 8 位 BMP,它警告说需要它是“真彩色”)
【讨论】:
以上是关于c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?的主要内容,如果未能解决你的问题,请参考以下文章
在 WM_CREATE 中加载多个位图的 C++ Win32 不会加载