gl画纹理texture


/*
* SDL OpenGL Tutorial.
* (c) Michael Vance, 2000
* briareos@lokigames.com
*
* Distributed under terms of the LGPL.
*/

#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include <stdio.h>
#include <stdlib.h>

/*******************************************************************
* *
* Using SDL With OpenGL *
* *
* Tutorial by Kyle Foley (sdw) *
* *
* http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
* *
*******************************************************************/

 

#include <stdio.h>

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

// Slightly different SDL initialization
if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL | SDL_FULLSCREEN ); // *changed*
if ( !screen ) {
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}

// Set the OpenGL state after creating the context with SDL_SetVideoMode

glClearColor( 0, 0, 0, 0 );

glEnable( GL_TEXTURE_2D ); // Need this to display a texture

glViewport( 0, 0, 640, 480 );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho( 0, 640, 480, 0, -1, 1 );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

// Load the OpenGL texture

GLuint texture; // Texture object handle
SDL_Surface *surface; // Gives us the information to make the texture

if ( (surface = SDL_LoadBMP("image.bmp")) ) {

// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}

// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}

// 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, 3, surface->w, surface->h, 0,
GL_BGR, GL_UNSIGNED_BYTE, surface->pixels );
}
else {
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}

// Free the SDL_Surface only if it was successfully created
if ( surface ) {
SDL_FreeSurface( surface );
}

// Clear the screen before drawing
glClear( GL_COLOR_BUFFER_BIT );

// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, texture );

glBegin( GL_QUADS );
// Top-left vertex (corner)
glTexCoord2i( 0, 0 );
glVertex3f( 100, 100, 0 );

// Bottom-left vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( 228, 100, 0 );

// Bottom-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( 228, 228, 0 );

// Top-right vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( 100, 228, 0 );
glEnd();

SDL_GL_SwapBuffers();

// Wait for 3 seconds to give us a chance to see the image
SDL_Delay(30000);

// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &texture );

SDL_Quit();

return 0;
}



旋转球
http://www.libsdl.org/docs/html/guidevideoopengl.html
/* * SDL OpenGL Tutorial. * (c) Michael Vance, 2000 * briareos@lokigames.com * * Distributed under terms of the LGPL. */ #include <SDL/SDL.h> #include <GL/gl.h> #include <GL/glu.h> #include <stdio.h> #include <stdlib.h> static GLboolean should_rotate = GL_TRUE; static void quit_tutorial( int code ) { /* * Quit SDL so we can release the fullscreen * mode and restore the previous video settings, * etc. */ SDL_Quit( ); /* Exit program. */ exit( code ); } static void handle_key_down( SDL_keysym* keysym ) { /* * We're only interested if 'Esc' has * been presssed. * * EXERCISE: * Handle the arrow keys and have that change the * viewing position/angle. */ switch( keysym->sym ) { case SDLK_ESCAPE: quit_tutorial( 0 ); break; case SDLK_SPACE: should_rotate = !should_rotate; break; default: break; } } static void process_events( void ) { /* 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 presses. */ handle_key_down( &event.key.keysym ); break; case SDL_QUIT: /* Handle quit requests (like Ctrl-c). */ quit_tutorial( 0 ); break; } } } static void draw_screen( void ) { /* Our angle of rotation. */ static float angle = 0.0f; /* * EXERCISE: * Replace this awful mess with vertex * arrays and a call to glDrawElements. * * EXERCISE: * After completing the above, change * it to use compiled vertex arrays. * * EXERCISE: * Verify my windings are correct here ;). */ static GLfloat v0[] = { -1.0f, -1.0f, 1.0f }; static GLfloat v1[] = { 1.0f, -1.0f, 1.0f }; static GLfloat v2[] = { 1.0f, 1.0f, 1.0f }; static GLfloat v3[] = { -1.0f, 1.0f, 1.0f }; static GLfloat v4[] = { -1.0f, -1.0f, -1.0f }; static GLfloat v5[] = { 1.0f, -1.0f, -1.0f }; static GLfloat v6[] = { 1.0f, 1.0f, -1.0f }; static GLfloat v7[] = { -1.0f, 1.0f, -1.0f }; static GLubyte red[] = { 255, 0, 0, 255 }; static GLubyte green[] = { 0, 255, 0, 255 }; static GLubyte blue[] = { 0, 0, 255, 255 }; static GLubyte white[] = { 255, 255, 255, 255 }; static GLubyte yellow[] = { 0, 255, 255, 255 }; static GLubyte black[] = { 0, 0, 0, 255 }; static GLubyte orange[] = { 255, 255, 0, 255 }; static GLubyte purple[] = { 255, 0, 255, 0 }; /* 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 ); /* Rotate. */ glRotatef( angle, 0.0, 1.0, 0.0 ); if( should_rotate ) { if( ++angle > 360.0f ) { angle = 0.0f; } } /* Send our triangle data to the pipeline. */ glBegin( GL_TRIANGLES ); glColor4ubv( red ); glVertex3fv( v0 ); glColor4ubv( green ); glVertex3fv( v1 ); glColor4ubv( blue ); glVertex3fv( v2 ); glColor4ubv( red ); glVertex3fv( v0 ); glColor4ubv( blue ); glVertex3fv( v2 ); glColor4ubv( white ); glVertex3fv( v3 ); glColor4ubv( green ); glVertex3fv( v1 ); glColor4ubv( black ); glVertex3fv( v5 ); glColor4ubv( orange ); glVertex3fv( v6 ); glColor4ubv( green ); glVertex3fv( v1 ); glColor4ubv( orange ); glVertex3fv( v6 ); glColor4ubv( blue ); glVertex3fv( v2 ); glColor4ubv( black ); glVertex3fv( v5 ); glColor4ubv( yellow ); glVertex3fv( v4 ); glColor4ubv( purple ); glVertex3fv( v7 ); glColor4ubv( black ); glVertex3fv( v5 ); glColor4ubv( purple ); glVertex3fv( v7 ); glColor4ubv( orange ); glVertex3fv( v6 ); glColor4ubv( yellow ); glVertex3fv( v4 ); glColor4ubv( red ); glVertex3fv( v0 ); glColor4ubv( white ); glVertex3fv( v3 ); glColor4ubv( yellow ); glVertex3fv( v4 ); glColor4ubv( white ); glVertex3fv( v3 ); glColor4ubv( purple ); glVertex3fv( v7 ); glColor4ubv( white ); glVertex3fv( v3 ); glColor4ubv( blue ); glVertex3fv( v2 ); glColor4ubv( orange ); glVertex3fv( v6 ); glColor4ubv( white ); glVertex3fv( v3 ); glColor4ubv( orange ); glVertex3fv( v6 ); glColor4ubv( purple ); glVertex3fv( v7 ); glColor4ubv( green ); glVertex3fv( v1 ); glColor4ubv( red ); glVertex3fv( v0 ); glColor4ubv( yellow ); glVertex3fv( v4 ); glColor4ubv( green ); glVertex3fv( v1 ); glColor4ubv( yellow ); glVertex3fv( v4 ); glColor4ubv( black ); glVertex3fv( v5 ); glEnd( ); /* * EXERCISE: * Draw text telling the user that 'Spc' * pauses the rotation and 'Esc' quits. * Do it using vetors and textured quads. */ /* * Swap the buffers. This this tells the driver to * render the next frame from the contents of the * back-buffer, and to set all rendering operations * to occur on what was the front-buffer. * * Double buffering prevents nasty visual tearing * from the application drawing on areas of the * screen that are being updated at the same time. */ SDL_GL_SwapBuffers( ); } static void setup_opengl( int width, int height ) { float ratio = (float) width / (float) height; /* Our shading model--Gouraud (smooth). */ glShadeModel( GL_SMOOTH ); /* Culling. */ glCullFace( GL_BACK ); glFrontFace( GL_CCW ); glEnable( GL_CULL_FACE ); /* 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( ); /* * EXERCISE: * Replace this with a call to glFrustum. */ gluPerspective( 60.0, ratio, 1.0, 1024.0 ); } int main( int argc, char* argv[] ) { /* Information about the current video settings. */ const SDL_VideoInfo* info = NULL; /* Dimensions of our window. */ int width = 0; int height = 0; /* Color depth in bits of our window. */ int bpp = 0; /* Flags we will pass into SDL_SetVideoMode. */ int flags = 0; /* First, initialize SDL's video subsystem. */ if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { /* Failed, exit. */ fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) ); quit_tutorial( 1 ); } /* Let's get some video information. */ info = SDL_GetVideoInfo( ); if( !info ) { /* This should probably never happen. */ fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) ); quit_tutorial( 1 ); } /* * Set our width/height to 640/480 (you would * of course let the user decide this in a normal * app). We get the bpp we will request from * the display. On X11, VidMode can't change * resolution, so this is probably being overly * safe. Under Win32, ChangeDisplaySettings * can change the bpp. */ width = 640; height = 480; bpp = info->vfmt->BitsPerPixel; /* * Now, we want to setup our requested * window attributes for our OpenGL window. * We want *at least* 5 bits of red, green * and blue. We also want at least a 16-bit * depth buffer. * * The last thing we do is request a double * buffered window. '1' turns on double * buffering, '0' turns it off. * * Note that we do not use SDL_DOUBLEBUF in * the flags to SDL_SetVideoMode. That does * not affect the GL attribute state, only * the standard 2D blitting setup. */ 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 ); /* * We want to request that SDL provide us * with an OpenGL window, in a fullscreen * video mode. * * EXERCISE: * Make starting windowed an option, and * handle the resize events properly with * glViewport. */ flags = SDL_OPENGL | SDL_FULLSCREEN; /* * Set the video mode */ if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { /* * This could happen for a variety of reasons, * including DISPLAY not being set, the specified * resolution not being available, etc. */ fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) ); quit_tutorial( 1 ); } /* * At this point, we should have a properly setup * double-buffered window for use with OpenGL. */ setup_opengl( width, height ); /* * Now we want to begin our normal app process-- * an event loop with a lot of redrawing. */ while( 1 ) { /* Process incoming events. */ process_events( ); /* Draw the screen. */ draw_screen( ); } /* * EXERCISE: * Record timings using SDL_GetTicks() and * and print out frames per second at program * end. */ /* Never reached. */ return 0; }

 

 

显示黑屏的例子:

#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

/* 屏幕宽,高和颜色位数 */
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 16

/* 设置布尔值 */
#define TRUE 1
#define FALSE 0

/* SDL表面 */
SDL_Surface *surface;

/* 用来释放/销毁程序资源,并返回桌面 */
void Quit(int returnCode) {
/* 清除窗口 */
SDL_Quit();

/* 退出 */
exit(returnCode);
}

/* 窗口更改后重新设置视点(观察点) */
int resizeWindow(int width, int height) {
/* 高与宽的比例 */
GLfloat ratio;

/* 防止除零 */
if (height == 0)
height = 1;

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

/* 设置视点 */
glViewport(0, 0, (GLint) width, (GLint) height);

/* 选择投影矩阵 */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

/* 设置透视 */
gluPerspective(45.0f, ratio, 0.1f, 100.0f);

/* 选择模型观察矩阵 */
glMatrixMode(GL_MODELVIEW);

/* 重置模型观察矩阵 */
glLoadIdentity();

return (TRUE);
}

/* 获得键盘按键事件 */
void handleKeyPress(SDL_keysym *keysym) {
switch (keysym->sym) {
case SDLK_ESCAPE:
/* ESC按下时 */
Quit(0);
break;
case SDLK_F1:
/* F1按下时
* 触发全屏模式
*/
SDL_WM_ToggleFullScreen(surface);
break;
default:
break;
}

return;
}

/* OpenGL初始化函数 */
int initGL(void) {

/* 启用阴影平滑 */
glShadeModel(GL_SMOOTH);

/* 设置黑色背景 */
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

/* 设置深度缓存 */
glClearDepth(1.0f);

/* 启用深度测试 */
glEnable(GL_DEPTH_TEST);

/* 所作深度测试类型 */
glDepthFunc(GL_LEQUAL);

/* 告知系统对透视进行修正 */
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

return (TRUE);
}

/* 绘制代码 */
int drawGLScene(void) {
/* 计算fps */
static GLint T0 = 0;
static GLint Frames = 0;

/* 清除屏幕及深度缓冲 */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

/* 绘制屏幕 */
SDL_GL_SwapBuffers();

/* 自增长桢的计算 */
Frames++;
{
GLint t = SDL_GetTicks();
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}

return (TRUE);
}

/* 程序主函数 */
int main(int argc, char **argv) {
/* 通过SDL_SetVideoMode标志 */
int videoFlags;
/* 主循环变量 */
int done = FALSE;
/* SDL事件 */
SDL_Event event;
/* 显示一些信息在屏幕 */
const SDL_VideoInfo *videoInfo;
/* 窗口激活标志 */
int isActive = TRUE;

/* 初始化 SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
Quit(1);
}

/* 获得视频信息 */
videoInfo = SDL_GetVideoInfo();

if (!videoInfo) {
fprintf(stderr, "Video query failed: %s\n", SDL_GetError());
Quit(1);
}

/* 通过SDL_SetVideoMode标志 */
videoFlags = SDL_OPENGL; /* 在SDL中启用OpenGL */
videoFlags |= SDL_GL_DOUBLEBUFFER; /* 启用双缓冲 */
videoFlags |= SDL_HWPALETTE; /* 硬件保存调色板 */
videoFlags |= SDL_RESIZABLE; /* 窗口可更改 */

/* 检测表面是否可以保存入内存 */
if (videoInfo->hw_available){
printf("===support.\n");
videoFlags |= SDL_HWSURFACE;
}else{
printf("===not support.\n");
videoFlags |= SDL_SWSURFACE;
}

/* 测试硬件翻转 */
if (videoInfo->blit_hw)
videoFlags |= SDL_HWACCEL;

/* 设置OpenGL双缓冲 */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

/* 获得SDL表面 */
surface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags);

/* 验证表面 */
if (!surface) {
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
Quit(1);
}

/* 初始化 OpenGL */
if (initGL() == FALSE) {
fprintf(stderr, "Could not initialize OpenGL.\n");
Quit(1);
}

/* 初始化窗口 */
resizeWindow(SCREEN_WIDTH, SCREEN_HEIGHT);

/* 等待事件 */
while (!done) {
/* 获得事件队列 */

while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_ACTIVEEVENT:
/* 不在焦点时候或最小化,不需要绘制
*/
if (event.active.gain == 0)
isActive = FALSE;
else
isActive = TRUE;
break;
case SDL_VIDEORESIZE:
/* 获得改变窗口事件 */
surface = SDL_SetVideoMode(event.resize.w, event.resize.h, 16, videoFlags);
if (!surface) {
fprintf(stderr, "Could not get a surface after resize: %s\n", SDL_GetError());
Quit(1);
}
resizeWindow(event.resize.w, event.resize.h);
break;
case SDL_KEYDOWN:
/* 获得键盘按下 */
handleKeyPress(&event.key.keysym);
break;
case SDL_QUIT:
/* 获得退出请求 */
done = TRUE;
break;
default:
break;
}
}

/* 绘制场景 */
if (isActive)
drawGLScene();
}

/* 清除本身并退出 */
Quit(0);

/* 不可能执行这里了 */
return (0);
}