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 中的多维数据集中?的主要内容,如果未能解决你的问题,请参考以下文章

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

在 WM_CREATE 中加载多个位图的 C++ Win32 不会加载

如何将位图文件加载到 BitmapData 对象中?

在 Ubuntu 上使用 C++ 和 cmake 使用 SDL2 + SDL2Image 加载 PNG

将 SDL 示例移植到 OpenGL 和 C++

C++如何把位图保存到数组中