SDL2.0上手试用

发表于2017-09-11
评论0 1.9k浏览

前言

       个人喜好原因,写OpenGL的程序都喜欢用SDL做框架,没有Qt那么臃肿,也没有glut那么坑跌,在不失灵活性的情况下保持了自己的轻量。SDL2.0在今年很早的时候时候就发布了,所以下面就和大家介绍介绍SDL2.0的使用。

      

下面是SDL2主要的几点新特性:

全硬件加速
支持OpenGL3.0
支持OpenGL ES
支持Android和iOS

跨平台支持Windows,MacOSX和LInux

修改了很多bug

...


编译安装

从官网下载最新版2.0.1的源码,解压后cd进目录,依次执行:

./autogen

./configura

make

sudu make install

一切顺利的话SDL2.0就安装编译好了。

库文件在 /usr/local/lib中

头文件在 /usr/local/include/SDL2 中。


加载显示一张图片

感觉SDL的1.2和2.0差别还是挺大的。看代码:

  1. #include   
  2. #include     
  3. #include     
  4. #include     
  5. using namespace std;  
  6. int main()  
  7. {  
  8.     //Start SDL    
  9.     if (SDL_Init(SDL_INIT_VIDEO) != 0)  
  10.     {  
  11.         cout << "SDL_Init Error: " << SDL_GetError() << endl;  
  12.         return 1;  
  13.     }  
  14.       
  15.     SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 871, 564, SDL_WINDOW_SHOWN);  
  16.     if (win == nullptr)  
  17.     {  
  18.         cout << "SDL_CreateWindow Error: " << SDL_GetError() << endl;  
  19.         return 1;  
  20.     }  
  21.       
  22.     SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);  
  23.     if (ren == nullptr)  
  24.     {  
  25.         cout << "SDL_CreateRenderer Error: " << SDL_GetError() << endl;  
  26.         return 1;  
  27.     }  
  28.       
  29.     SDL_Surface *bmp = SDL_LoadBMP("girl.bmp");  
  30.     if (bmp == nullptr)  
  31.     {  
  32.         cout << "SDL_LoadBMP Error: " << SDL_GetError() << endl;  
  33.         return 1;  
  34.     }  
  35.       
  36.     SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);  
  37.     SDL_FreeSurface(bmp);  
  38.     if (tex == nullptr)  
  39.     {  
  40.         cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << endl;  
  41.         return 1;  
  42.     }  
  43.       
  44.     SDL_RenderClear(ren);  
  45.     SDL_RenderCopy(ren, tex, NULL, NULL);  
  46.     SDL_RenderPresent(ren);  
  47.       
  48.     SDL_Delay(2000);  
  49.       
  50.     SDL_DestroyTexture(tex);  
  51.     SDL_DestroyRenderer(ren);  
  52.     SDL_DestroyWindow(win);  
  53.     //Quit SDL    
  54.         SDL_Quit();   
  55.     cout<<"Hello"<<endl;  < span=""></endl;  <>
  56.     return 1;  
  57. }  

代码还是蛮简单的,先是初始化SDL,再依次 初始化Window ->初始化Render ->加载图片 -> 生成纹理 ->渲染纹理 ->释放内存,记得在当前目录放一张 girl.bmp.运行结果:




基于SDL2的OpenGL编程

相对于SDL1.2中的函数接口,SDL2改变得还是比较大的,其中的设计得会更加“现代化”一些,用起来会更加方便,以前用过SDL1.2的需要重新熟悉一下。

  1. #include   
  2. #include     
  3. #include     
  4. #include     
  5. using namespace std;  
  6.   
  7. const int SCREEN_WIDTH = 800;    
  8. const int SCREEN_HEIGHT =600;   
  9. SDL_Window *mainwindow; /* Our window handle */  
  10. SDL_GLContext maincontext; /* Our opengl context handle */  
  11.   
  12. /* A simple function that prints a message, the error code returned by SDL, 
  13.  * and quits the application */  
  14. void sdldie(const char *msg)  
  15. {  
  16.     printf("%s: %s\n", msg, SDL_GetError());  
  17.     SDL_Quit();  
  18.     exit(1);  
  19. }  
  20.   
  21. void quit( int code )    
  22. {    
  23.     SDL_Quit( );    
  24.     /* Exit program. */    
  25.     exit( code );    
  26. }    
  27.   
  28. void checkSDLError(int line = -1)  
  29. {  
  30. #ifndef NDEBUG  
  31.         const char *error = SDL_GetError();  
  32.         if (*error != '\0')  
  33.         {  
  34.                 printf("SDL Error: %s\n", error);  
  35.                 if (line != -1)  
  36.                         printf("   line: %i\n", line);  
  37.                 SDL_ClearError();  
  38.         }  
  39. #endif  
  40. }  
  41.   
  42. void initGL( int width, int height )    
  43. {    
  44.     float ratio = (float) width / (float) height;    
  45.     // Our shading model--Gouraud (smooth).    
  46.     glShadeModel( GL_SMOOTH );    
  47.     // Set the clear color.    
  48.     glClearColor( 0, 0, 0, 0 );    
  49.     // Setup our viewport.    
  50.     glViewport( 0, 0, width, height );    
  51.     //Change to the projection matrix and set our viewing volume.    
  52.     glMatrixMode( GL_PROJECTION );    
  53.     glLoadIdentity();    
  54.     gluPerspective( 60.0, ratio, 1.0, 100.0 );    
  55. }    
  56.   
  57. void initSDL()  
  58. {  
  59.     if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */  
  60.         sdldie("Unable to initialize SDL"); /* Or die on error */  
  61.    
  62.     /* Request opengl 3.2 context. 
  63.      * SDL doesn't have the ability to choose which profile at this time of writing, 
  64.      * but it should default to the core profile */  
  65.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);  
  66.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);  
  67.    
  68.     /* Turn on double buffering with a 24bit Z buffer. 
  69.      * You may need to change this to 16 or 32 for your system */  
  70.     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);  
  71.     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);  
  72.    
  73.     /* Create our window centered at 512x512 resolution */  
  74.     mainwindow = SDL_CreateWindow("OpenGL in SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,  
  75.         SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);  
  76.     if (!mainwindow) /* Die if creation failed */  
  77.         sdldie("Unable to create window");  
  78.    
  79.     checkSDLError(__LINE__);  
  80.    
  81.     /* Create our opengl context and attach it to our window */  
  82.     maincontext = SDL_GL_CreateContext(mainwindow);  
  83.     checkSDLError(__LINE__);  
  84.    
  85.     /* This makes our buffer swap syncronized with the monitor's vertical refresh */  
  86.     SDL_GL_SetSwapInterval(1);  
  87. }  
  88.   
  89. void renderGL()  
  90. {  
  91.      // Clear the color and depth buffers.    
  92.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    
  93.     // We don't want to modify the projection matrix. */    
  94.     glMatrixMode( GL_MODELVIEW );    
  95.     glLoadIdentity( );    
  96.     // Move down the z-axis.    
  97.     glTranslatef( 0.0, 0.0, -5.0 );    
  98.     //Draw a square    
  99.     glBegin(GL_QUADS);    
  100.     glColor3f(1.0f,0.0f,0.0f);    
  101.     glVertex3f(-1.0f  , -1.0f  ,  1.0f  );    
  102.     glColor3f(0.0f,1.0f,0.0f);    
  103.     glVertex3f( 1.0f  , -1.0f  ,  1.0f  );    
  104.     glColor3f(0.0f,0.0f,1.0f);    
  105.     glVertex3f( 1.0f  ,  1.0f  ,  1.0f  );    
  106.     glColor3f(1.0f,1.0f,0.0f);    
  107.     glVertex3f(-1.0f  ,  1.0f  ,  1.0f  );    
  108.     glEnd();    
  109.     SDL_GL_SwapWindow(mainwindow);  
  110. }  
  111.   
  112. void resizeGL(int width,int height)    
  113. {    
  114.     if ( height == 0 )    
  115.     {    
  116.         height = 1;    
  117.     }    
  118.     //Reset View    
  119.     glViewport( 0, 0, (GLint)width, (GLint)height );    
  120.     //Choose the Matrix mode    
  121.     glMatrixMode( GL_PROJECTION );    
  122.     //reset projection    
  123.     glLoadIdentity();    
  124.     //set perspection    
  125.     gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );    
  126.     //choose Matrix mode    
  127.     glMatrixMode( GL_MODELVIEW );    
  128.     glLoadIdentity();    
  129.       
  130. }    
  131.   
  132. void handleKeyEvent( SDL_Keysym* keysym )    
  133. {    
  134.     switch( keysym->sym )    
  135.     {    
  136.     case SDLK_ESCAPE:    
  137.         quit( 0 );    
  138.         break;    
  139.     case SDLK_SPACE:    
  140.      cout<<"Space"<<endl;  < span=""></endl;  <>
  141.         break;    
  142.     default:    
  143.         break;    
  144.     }    
  145. }   
  146.   
  147. void handleEvents()    
  148. {    
  149.     // Our SDL event placeholder.    
  150.     SDL_Event event;    
  151.     //Grab all the events off the queue.    
  152.     while( SDL_PollEvent( &event ) ) {    
  153.         switch( event.type ) {    
  154.         case SDL_KEYDOWN:    
  155.             // Handle key Event    
  156.             handleKeyEvent( &event.key.keysym );    
  157.             break;    
  158.         case SDL_QUIT:    
  159.             // Handle quit requests (like Ctrl-c).    
  160.             quit( 0 );    
  161.             break;    
  162.         case SDL_WINDOWEVENT:    
  163.             if(event.window.event == SDL_WINDOWEVENT_RESIZED)  
  164.             {  
  165.                 if ( mainwindow )    
  166.                 {    
  167.                     int tmpX,tmpY;  
  168.                     SDL_GetWindowSize(mainwindow,&tmpX,&tmpY);  
  169.                     resizeGL(tmpX, tmpY);   
  170.                       
  171.                 }    
  172.             }  
  173.             SDL_GL_SwapWindow(mainwindow);  
  174.             break;    
  175.         }    
  176.     }    
  177. }   
  178.   
  179. /* Our program's entry point */  
  180. int main(int argc, char *argv[])  
  181. {  
  182.     initSDL();  
  183.     initGL(SCREEN_WIDTH, SCREEN_HEIGHT);  
  184.     renderGL( );    
  185.     while(true)  
  186.     {  
  187.         /* Process incoming events. */    
  188.         handleEvents( );    
  189.         /*Render scene*/  
  190.         renderGL();   
  191.     }  
  192.    
  193.     return 0;  
  194. }  

需要说明的时候__LINE__这个宏,它主要是用来调试的,表示当前的代码行数,

用下面的命令来编译:

g test.cpp -o test -lSDL2 -lGL -lGLU -std=c 11 

运行结果:



编译运行Android中的SDL2

注:最好在Ubuntu 下来进行交叉编译,测试过Opensuse,未果。

在SDL的源码文件夹中有相应的android工程模板 android-project.

首先是交叉编译。

1.创建android-project/jni/SDL文件夹

2.将SDL源码目录下的src 和include文件夹还有Android.mk拷贝到刚才创建的目录

3.在 android-project/jni/src 中创建main.c

这里从手机里面加载一张图片来显示。 copy

  1. #include "SDL.h"  
  2.   
  3. int main(int argc, char* argv[])  
  4. {  
  5.     //Start SDL    
  6.     if (SDL_Init(SDL_INIT_VIDEO) != 0)  
  7.     {  
  8.         return 1;  
  9.     }  
  10.       
  11.     SDL_Window *win = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_SHOWN);  
  12.   
  13.       
  14.     SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);  
  15.   
  16.       
  17.     SDL_Surface *bmp = SDL_LoadBMP("/sdcard/boss.bmp");  
  18.   
  19.       
  20.     SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);  
  21.     SDL_FreeSurface(bmp);  
  22.       
  23.     SDL_RenderClear(ren);  
  24.     SDL_RenderCopy(ren, tex, NULL, NULL);  
  25.     SDL_RenderPresent(ren);  
  26.       
  27.     SDL_Delay(2000);  
  28.       
  29.     SDL_DestroyTexture(tex);  
  30.     SDL_DestroyRenderer(ren);  
  31.     SDL_DestroyWindow(win);  
  32.       
  33.     //Quit SDL    
  34.     SDL_Quit();   
  35.     return 1;  
  36. }  

修改src/Android.mk文件,将YourSourceHere.c改为main.c.

4.在手机的sdcard根目录下面放一个boss.bmp,待会加载。

5.终端cd进android-project,执行

$NDK_ROOT/ndk-build

编译正常的话可以得到下面的结果:



6.用eclipse将项目导入,运行,得到结果:


如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引