SDL2.0上手试用
前言
个人喜好原因,写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差别还是挺大的。看代码:
- #include
- #include
- #include
- #include
- using namespace std;
- int main()
- {
- //Start SDL
- if (SDL_Init(SDL_INIT_VIDEO) != 0)
- {
- cout << "SDL_Init Error: " << SDL_GetError() << endl;
- return 1;
- }
- SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 871, 564, SDL_WINDOW_SHOWN);
- if (win == nullptr)
- {
- cout << "SDL_CreateWindow Error: " << SDL_GetError() << endl;
- return 1;
- }
- SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
- if (ren == nullptr)
- {
- cout << "SDL_CreateRenderer Error: " << SDL_GetError() << endl;
- return 1;
- }
- SDL_Surface *bmp = SDL_LoadBMP("girl.bmp");
- if (bmp == nullptr)
- {
- cout << "SDL_LoadBMP Error: " << SDL_GetError() << endl;
- return 1;
- }
- SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
- SDL_FreeSurface(bmp);
- if (tex == nullptr)
- {
- cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << endl;
- return 1;
- }
- SDL_RenderClear(ren);
- SDL_RenderCopy(ren, tex, NULL, NULL);
- SDL_RenderPresent(ren);
- SDL_Delay(2000);
- SDL_DestroyTexture(tex);
- SDL_DestroyRenderer(ren);
- SDL_DestroyWindow(win);
- //Quit SDL
- SDL_Quit();
- cout<<"Hello"<<endl; < span=""></endl; <>
- return 1;
- }
代码还是蛮简单的,先是初始化SDL,再依次 初始化Window ->初始化Render ->加载图片 -> 生成纹理 ->渲染纹理 ->释放内存,记得在当前目录放一张 girl.bmp.运行结果:
基于SDL2的OpenGL编程
相对于SDL1.2中的函数接口,SDL2改变得还是比较大的,其中的设计得会更加“现代化”一些,用起来会更加方便,以前用过SDL1.2的需要重新熟悉一下。
- #include
- #include
- #include
- #include
- using namespace std;
- const int SCREEN_WIDTH = 800;
- const int SCREEN_HEIGHT =600;
- SDL_Window *mainwindow; /* Our window handle */
- SDL_GLContext maincontext; /* Our opengl context handle */
- /* A simple function that prints a message, the error code returned by SDL,
- * and quits the application */
- void sdldie(const char *msg)
- {
- printf("%s: %s\n", msg, SDL_GetError());
- SDL_Quit();
- exit(1);
- }
- void quit( int code )
- {
- SDL_Quit( );
- /* Exit program. */
- exit( code );
- }
- void checkSDLError(int line = -1)
- {
- #ifndef NDEBUG
- const char *error = SDL_GetError();
- if (*error != '\0')
- {
- printf("SDL Error: %s\n", error);
- if (line != -1)
- printf(" line: %i\n", line);
- SDL_ClearError();
- }
- #endif
- }
- void initGL( int width, int height )
- {
- float ratio = (float) width / (float) height;
- // Our shading model--Gouraud (smooth).
- glShadeModel( GL_SMOOTH );
- // Set the clear color.
- glClearColor( 0, 0, 0, 0 );
- // Setup our viewport.
- glViewport( 0, 0, width, height );
- //Change to the projection matrix and set our viewing volume.
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- gluPerspective( 60.0, ratio, 1.0, 100.0 );
- }
- void initSDL()
- {
- if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
- sdldie("Unable to initialize SDL"); /* Or die on error */
- /* Request opengl 3.2 context.
- * SDL doesn't have the ability to choose which profile at this time of writing,
- * but it should default to the core profile */
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
- /* Turn on double buffering with a 24bit Z buffer.
- * You may need to change this to 16 or 32 for your system */
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- /* Create our window centered at 512x512 resolution */
- mainwindow = SDL_CreateWindow("OpenGL in SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
- SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
- if (!mainwindow) /* Die if creation failed */
- sdldie("Unable to create window");
- checkSDLError(__LINE__);
- /* Create our opengl context and attach it to our window */
- maincontext = SDL_GL_CreateContext(mainwindow);
- checkSDLError(__LINE__);
- /* This makes our buffer swap syncronized with the monitor's vertical refresh */
- SDL_GL_SetSwapInterval(1);
- }
- void renderGL()
- {
- // Clear the color and depth buffers.
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- // We don't want to modify the projection matrix. */
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity( );
- // Move down the z-axis.
- glTranslatef( 0.0, 0.0, -5.0 );
- //Draw a square
- glBegin(GL_QUADS);
- glColor3f(1.0f,0.0f,0.0f);
- glVertex3f(-1.0f , -1.0f , 1.0f );
- glColor3f(0.0f,1.0f,0.0f);
- glVertex3f( 1.0f , -1.0f , 1.0f );
- glColor3f(0.0f,0.0f,1.0f);
- glVertex3f( 1.0f , 1.0f , 1.0f );
- glColor3f(1.0f,1.0f,0.0f);
- glVertex3f(-1.0f , 1.0f , 1.0f );
- glEnd();
- SDL_GL_SwapWindow(mainwindow);
- }
- void resizeGL(int width,int height)
- {
- if ( height == 0 )
- {
- height = 1;
- }
- //Reset View
- glViewport( 0, 0, (GLint)width, (GLint)height );
- //Choose the Matrix mode
- glMatrixMode( GL_PROJECTION );
- //reset projection
- glLoadIdentity();
- //set perspection
- gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
- //choose Matrix mode
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- }
- void handleKeyEvent( SDL_Keysym* keysym )
- {
- switch( keysym->sym )
- {
- case SDLK_ESCAPE:
- quit( 0 );
- break;
- case SDLK_SPACE:
- cout<<"Space"<<endl; < span=""></endl; <>
- break;
- default:
- break;
- }
- }
- void handleEvents()
- {
- // Our SDL event placeholder.
- SDL_Event event;
- //Grab all the events off the queue.
- while( SDL_PollEvent( &event ) ) {
- switch( event.type ) {
- case SDL_KEYDOWN:
- // Handle key Event
- handleKeyEvent( &event.key.keysym );
- break;
- case SDL_QUIT:
- // Handle quit requests (like Ctrl-c).
- quit( 0 );
- break;
- case SDL_WINDOWEVENT:
- if(event.window.event == SDL_WINDOWEVENT_RESIZED)
- {
- if ( mainwindow )
- {
- int tmpX,tmpY;
- SDL_GetWindowSize(mainwindow,&tmpX,&tmpY);
- resizeGL(tmpX, tmpY);
- }
- }
- SDL_GL_SwapWindow(mainwindow);
- break;
- }
- }
- }
- /* Our program's entry point */
- int main(int argc, char *argv[])
- {
- initSDL();
- initGL(SCREEN_WIDTH, SCREEN_HEIGHT);
- renderGL( );
- while(true)
- {
- /* Process incoming events. */
- handleEvents( );
- /*Render scene*/
- renderGL();
- }
- return 0;
- }
需要说明的时候__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
- #include "SDL.h"
- int main(int argc, char* argv[])
- {
- //Start SDL
- if (SDL_Init(SDL_INIT_VIDEO) != 0)
- {
- return 1;
- }
- SDL_Window *win = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_SHOWN);
- SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
- SDL_Surface *bmp = SDL_LoadBMP("/sdcard/boss.bmp");
- SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
- SDL_FreeSurface(bmp);
- SDL_RenderClear(ren);
- SDL_RenderCopy(ren, tex, NULL, NULL);
- SDL_RenderPresent(ren);
- SDL_Delay(2000);
- SDL_DestroyTexture(tex);
- SDL_DestroyRenderer(ren);
- SDL_DestroyWindow(win);
- //Quit SDL
- SDL_Quit();
- return 1;
- }
修改src/Android.mk文件,将YourSourceHere.c改为main.c.
4.在手机的sdcard根目录下面放一个boss.bmp,待会加载。
5.终端cd进android-project,执行
$NDK_ROOT/ndk-build
编译正常的话可以得到下面的结果:
6.用eclipse将项目导入,运行,得到结果: