SDL入门学习续-在SDL中使用OpenGL

SDL 1

 配置好SDL之后,就想在SDL中使用openGL,原以为会像在GLFW中那样简单的,实际上确花费了一整个下午不断查看文档,实例才搞定问题。

总结如下:

1)SDL对OpenGL进行了部分的封装,一些OpenGL的函数需要用SDL来实现,而不是像GLFW中那样直接用;

2)SDL的事件机制花费了一些时间来理解;

3)在处理OpenGL窗口大小变化的时候,需要先调用SDL_SetVideoMode才可以得到正确结果。

最终基本实现了一个opengl的小型框架,包括一些简单的事件处理。

代码:

/*****************************************************************************
Copyright: 2012, ustc All rights reserved.
contact:[email protected]
File name: main.c
Description:using opengl in SDL.
Author:Silang Quan
Version: 1.0
Date: 2012.12.01
*****************************************************************************/
#include 
#include 
#include 
#include 
#include 
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT =800;
const int SCREEN_BPP = 32;
SDL_Surface *screen;
//Whether the window is windowed or not
bool windowed;
//Whether the window is fine
bool windowOK;
void quit( int code )
{
    SDL_Quit( );
    /* Exit program. */
    exit( code );
}
void toggle_fullscreen()
{
	//If the screen is windowed
	if( windowed == true )
	{
		//Set the screen to fullscreen
		screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE| SDL_FULLSCREEN );

		//If there's an error
		if( screen == NULL )
		{
			windowOK = false;
			return;
		}

		//Set the window state flag
		windowed = false;
	}
	//If the screen is fullscreen
	else if( windowed == false )
	{
		//Window the screen
		screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL|SDL_RESIZABLE );

		//If there's an error
		if( screen == NULL )
		{
			windowOK = false;
			return;
		}

		//Set the window state flag
		windowed = true;
	}
}
void handleKeyEvent( SDL_keysym* keysym )
{
    switch( keysym->sym )
	{
    case SDLK_ESCAPE:
        quit( 0 );
        break;
    case SDLK_SPACE:
        break;
    case SDLK_F1:
		toggle_fullscreen();
		break;
    default:
        break;
    }
}
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 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_VIDEORESIZE:
			//Handle resize event
            screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 16,
                                      SDL_OPENGL|SDL_RESIZABLE);
            if ( screen )
            {
                resizeGL(screen->w, screen->h);
            }
            break;
        }
    }
}

void initSDL(int width,int height,int bpp,int flags)
{
    // First, initialize SDL's video subsystem.
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        fprintf( stderr, "Video initialization failed: %s\n",
                 SDL_GetError( ) );
        quit( 1 );
    }
    atexit(SDL_Quit);
	//Set some Attribute of OpenGL in SDL
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

    //Set the video mode
    screen= SDL_SetVideoMode( width, height, bpp,flags);
    if(!screen )
    {
        fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError( ) );
        quit( 1 );
    windowed=false;
	}
	else windowed=true;
    resizeGL(screen->w, screen->h);
    //Set caption
    SDL_WM_SetCaption( "OpenGL Test", NULL );
}
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_SwapBuffers( );
}
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 );
}
int main( int argc, char* argv[] )
{

	// Color depth in bits of our window.
	int flags= SDL_OPENGL|SDL_RESIZABLE;
	//Set the SDL
	initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);
	//Set the OpenGL
	initGL(SCREEN_WIDTH, SCREEN_HEIGHT );

    //main loop
    while(true)
	{
        /* Process incoming events. */
        handleEvents( );
        /* Draw the screen. */
        renderGL( );
    }
    return 0;
}



编译命令:

 g++ main.c -o mian -lSDL -lglut -lGLU

#in opensuse
g++ main.c -o main -lSDL -lGL -lGLU


SDLOpenGLFramework

这里给一个C++写的OpenGL编程框架。

https://github.com/SilangQuan/SDLOpenGLFramework



SDL2

SDL2中接口改变了很多,下面是一个简单的可运行的例子。

环境:Windows 10 64bit VS2015 SDL2.0.4


#define GLUT_DISABLE_ATEXIT_HACK
#include "SDL/SDL.h"
#include 

#include "GL/glew.h"
#include "GL/wglew.h"
#include  
#include   
#include 
#include "iostream"
#include 

using namespace std;


#include 

#define _USE_MATH_DEFINES
#include 

#include 

constexpr int SCREEN_WIDTH = 800;
constexpr int SCREEN_HEIGHT = 600;

constexpr int OPENGL_MAJOR_VERSION = 2;
constexpr int OPENGL_MINOR_VERSION = 1;

constexpr SDL_GLprofile OPENGL_PROFILE = SDL_GLprofile::SDL_GL_CONTEXT_PROFILE_CORE;

void perspectiveGL(GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar) {

	GLdouble fW, fH;

	fH = tan(fovY / 360 * M_PI) * zNear;
	fW = fH * aspect;

	glFrustum(-fW, fW, -fH, fH, zNear, zFar);

}

void Display_InitGL() {

	/* Enable smooth shading */
	glShadeModel(GL_SMOOTH);

	/* Set the background red */
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	/* Depth buffer setup */
	glClearDepth(1.0f);

	/* Enables Depth Testing */
	glEnable(GL_DEPTH_TEST);

	/* The Type Of Depth Test To Do */
	glDepthFunc(GL_LEQUAL);

	/* Really Nice Perspective Calculations */
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

/* function to reset our viewport after a window resize */
int Display_SetViewport(int width, int height) {

	/* Height / width ration */
	GLfloat ratio;

	/* Protect against a divide by zero */
	if (height == 0) {
		height = 1;
	}

	ratio = (GLfloat)width / (GLfloat)height;

	/* Setup our viewport. */
	glViewport(0, 0, (GLsizei)width, (GLsizei)height);

	/* change to the projection matrix and set our viewing volume. */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* Set our perspective */
	perspectiveGL(45.0f, ratio, 0.1f, 100.0f);

	/* Make sure we're chaning the model view and not the projection */
	glMatrixMode(GL_MODELVIEW);

	/* Reset The View */
	glLoadIdentity();

	return 1;
}

void Display_Render(SDL_Window* displayWindow) {

	/* Clear The Screen And The Depth Buffer */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glColor4f(1, 1, 0, 1.0);

	/* Move Left 1.5 Units And Into The Screen 6.0 */
	glLoadIdentity();
	glTranslatef(-1.5f, 0.0f, -6.0f);

	glBegin(GL_TRIANGLES); /* Drawing Using Triangles */
	glColor3f(1.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, 1.0f, 0.0f); /* Top */
	glColor3f(0.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, -1.0f, 0.0f); /* Bottom Left */
	glColor3f(0.0f, 0.0f, 1.0f);
	glVertex3f(1.0f, -1.0f, 0.0f); /* Bottom Right */
	glEnd(); /* Finished Drawing The Triangle */

			 /* Move Right 3 Units */
	glTranslatef(3.0f, 0.0f, 0.0f);

	glBegin(GL_QUADS); /* Draw A Quad */
	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(); /* Done Drawing The Quad */

	SDL_GL_SwapWindow(displayWindow);

}

int main(int argc, char *argv[]) {

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		std::cerr << "There was an error initing SDL2: " << SDL_GetError() << std::endl;
		return 1;
	}

	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, OPENGL_PROFILE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR_VERSION);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR_VERSION);

	SDL_Window* displayWindow = SDL_CreateWindow("SDL2 X OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);

	if (displayWindow == nullptr) {
		std::cerr << "There was an error creating the window: " << SDL_GetError() << std::endl;
		return 1;
	}
	else
	{
		cout << "Creating SDL_Window created.............." << endl;
	}

	SDL_GLContext context = SDL_GL_CreateContext(displayWindow);

	if (context == nullptr) {
		std::cerr << "There was an error creating OpenGL context: " << SDL_GetError() << std::endl;
		return 1;
	}
	else
	{
		cout << "Creating  OpenGL context created.............." << endl;
	}

	GLenum err = glewInit();
	if (err != GLEW_OK)
	{
		cout << "-----------------GLEW init failed!------------- " << glewGetErrorString(err) << endl;
		exit(EXIT_FAILURE);
	}
	else
	{
		cout << "GLEW init successful!" << endl;
	}

	const unsigned char *version = glGetString(GL_VERSION);
	if (version == nullptr) 
	{
		std::cerr << "There was an error with OpenGL configuration:" << std::endl;
		return 1;
	}
	else
	{
		cout << "OpenGL Version: " << version << endl;
	}
	SDL_GL_MakeCurrent(displayWindow, context);

	Display_InitGL();

	Display_SetViewport(SCREEN_WIDTH, SCREEN_HEIGHT);

	Display_Render(displayWindow);

	SDL_Delay(2000);

	SDL_GL_DeleteContext(context);

	SDL_DestroyWindow(displayWindow);

	SDL_Quit();

	return 0;
}

运行结果




参考

SDL英文教程-http://lazyfoo.net/

你可能感兴趣的:(游戏开发)