和SDL在一起使用OpenGL

SDL許多月台((Linux/X11,Win32,BeOS,MacOS 經典/工具箱,MacOS未知數,FreeBSD/X11和Solaris/X11)上面有建立和使用OpenGL comtexts 的能力,這個允許你在你的OpenGL應用程式中使用SDL的音頻信號,事件觸摸,threads和.

Initialisation

使用OpenGL InitialisingSDL不在一般情況下是很和initialising SDL不同.有三個差異;你必須把 SDL_OPENGL傳給 SDL_SetVideoMode,你必須指定許多GL屬性((深度緩衝記憶體尺寸,framebuffer尺寸)使用 SDL_GL_SetAttribute和最後,如果你希望使用兩倍,當你緩衝必須不是透過把SDL_DOUBLEBUF旗幟傳給 SDL_SetVideoMode指定它作為一個GL屬性.

例子2-7.和OpenGL在一起預置SDL

    //關於目前影像設置的資訊.
const 
      info : PSDL_VideoInfo = nil;
    //我們視窗戶的尺度. 
var
    width : integer := 0;
    height : integer := 0;
    //在窗戶的彩色的深度.
   bpp : integer := 0;
      //我們將變為SDL_SetVideoMode通過的旗幟.
    flags : integer := 0;
begin
    //首先預置SDL的影像子系統.
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
    begin
         //未能,出去.
        MessageBox(0, PChar(Format('Video initialization failed : %s', [SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
        quit_tutorial( 1 );
    end;

    //讓我們得到一些影像資訊.
    info := SDL_GetVideoInfo;

    if( info = nil ) then
    begin
        //這個大概不應該發生.
        MessageBox(0, PChar(Format('Video query failed : %s', [SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
        quit_tutorial( 1 );
    end;

    
    {*落下我們寬度高度向640/480你是會
     *當然讓用戶在一正常標準中決定這個
     *app).我們得到bpp我們需求會從
     *展示.在X11上,VidMode不能改變
     *分解所以這個正大概過分是
     *保險箱.在Win32,ChangeDisplaySettings下面
     *能改變bpp.
     *}
    width := 640;
    height := 480;
    bpp := info.vfmt.BitsPerPixel;

    {*
     *現在,我們想要向組織我們需求
     為我們OpenGL窗戶*窗戶屬性.
     *我們想要紅色,綠色的*atleast* 5小塊
     *和藍色.我們也想要至少一16位
     *深度緩衝記憶體.
     *
     *我們做的最後一件事是需求一兩倍
     *當窗戶緩衝.在上'1'傾向增加一倍
     *當緩衝'0'關上它.
     *
     我們不在中使用SDL_DOUBLEBUF的*筆記
     *向SDL_SetVideoMode旗幟.那個做
     *不僅影響GL屬性狀態
     *標準2D blitting組織.
     *}
    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 );

    {*
     *我們想要請求SDL提供我們
     有一扇在一fullscreen中OpenGL窗戶的*
     *影像方式.
     *
     *練習:
     開始一選擇餘地有窗的*製造和
     *柄恰當調整事件的大小和在一起
     *glViewport.
     *}
    flags := SDL_OPENGL or SDL_FULLSCREEN;

    {*
     *設定影像方式
     *}
    if ( SDL_SetVideoMode( width, height, bpp, flags ) = 0 ) then      
    begin
        {* 
         *這個能為各種各樣的理由發生
         不要是設定*包括展示明確地講
         *不要是可用分解,等等
         *}
        MessageBox(0, PChar(Format('Video mode set failed : %s', [SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
quit_tutorial( 1 );
end;

圖畫

除了initialisation,是和任何另一API,例如大量在一起使用OpenGL,在SDL以內使用OpenGL都一樣.你仍然使用仍然功能呼叫和資料類型.但是如果你正使用兩倍當一展示緩衝,然後你必須使用SDL_GL_SwapBuffers 交換緩衝記憶體和更新展示.和SDL_GL_DOUBLEBUFFER在一起請求兩倍和OpenGL,使用在一起當SDL_GL_SetAttribute 緩衝,和使用 SDL_GL_GetAttribute看是否你事實上懂了.

現在一完整例子代碼列表下面被提出.

例子2-8.SDL和OpenGL

{*
 *SDL OpenGL個別輔導.
 *(c)7Michael Vance,2000
 *briareos@lokigames.com
 *
 *在LGPL的條款下分發. 
 *}

uses SDL,
     OpenGL;
var
  should_rotate : TGLboolean := GL_TRUE;

procedure quit_tutorial( code : integer );
begin
    {*
     *離開SDL,所以我們能釋放fullscreen
     *方式和交還前一影像設置
     *等等
     *}
    halt( code );
end;

procedure handle_key_down( keysym : PSDL_keysym );
begin
    {* 
     *如果'Esc',我們是僅僅有興趣
     *被敦促.
     *
     *練習: 
     *處理箭關鍵和有那改變
     *觀看位置/角.
     *}
    case keysym.sym  of 
      SDLK_ESCAPE:
        quit_tutorial( 0 );
      SDLK_SPACE:
        should_rotate := not should_rotate;
    else
        break;
    end;

end;

procedure process_events;
var
    //我們SDL事件佔位符號.
    event : TSDL_Event;
begin

//抓起所有的離開行列事件.
while( SDL_PollEvent( @event ) ) do
begin

case event.type_ of
SDL_KEYDOWN:
/*柄重要壓.*/
handle_key_down((&event.key.keysym);

SDL_QUIT:
/*柄離開(像Ctrl c)需求.*/
quit_tutorial((0);
end;

end;

end;

procedure draw_screen;
var
angle : single;
v0, v1, v2, v3, v4, v5, v6, v7 : array[0..2] of TGLFloat;
red, green, blue, white, yellow, black, orange, purple : TGLuByte;
begin
//我們轉動的角.
angle := 0.0;

{*
*練習:
*用頂點代替這可怕混亂
*陣列和一向glDrawElements呼叫.
*
*練習:
在完整上面的以後*,改變
*向使用它匯編頂點陣列.
*
*練習:
*查證我的繞這裡是恰當;)
*}
v0[ ] := { -1.0f, -1.0f, 1.0f };
v1[ ] := { 1.0f, -1.0f, 1.0f };
v2[ ] := { 1.0f, 1.0f, 1.0f };
v3[ ] := { -1.0f, 1.0f, 1.0f };
v4[ ] := { -1.0f, -1.0f, -1.0f };
v5[ ] := { 1.0f, -1.0f, -1.0f };
v6[ ] := { 1.0f, 1.0f, -1.0f };
v7[ ] := { -1.0f, 1.0f, -1.0f };
red[ ] := { 255, 0, 0, 255 };
green[ ] := { 0, 255, 0, 255 };
blue[ ] := { 0, 0, 255, 255 };
white[ ] := { 255, 255, 255, 255 };
yellow[ ] := { 0, 255, 255, 255 };
black[ ] := { 0, 0, 0, 255 };
orange[ ] := { 255, 255, 0, 255 };
purple[ ] := { 255, 0, 255, 0 };

//清理顏色和深度緩衝記憶體.
glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );

//我們不想要修改投影矩陣.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

//順Z軸而下移動.
glTranslatef((0.0,0.0,-5.0);

//旋轉.
glRotatef((角,0.0,1.0,0.0);

if ( should_rotate ) then
begin

inc( angle, 1 );
if ( angle > 360.0 ) then
begin
angle := 0.0;
end;

end;

//把我們三角形資料寄給管道.
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;

{*
*練習:
告訴用戶那'Spc'*拔取文本
轉動和'Esc'離開的*停頓.
*做它使用vetors和使方形天線具有特定結構.
*

*
*交換緩衝記憶體.這個這個告訴司機向
*放棄從目錄下一個結構的
*後面緩衝記憶體和設定所有的放棄運算
在什麼是前部緩衝記憶體上發生*.
*
*兩倍緩衝記憶體防止骯髒畫面流淚
從區域鼓勵應用*的
的同時被更新*銀幕.
*}
SDL_GL_SwapBuffers;
end;

procedure setup_opengl( width : integer; height : integer );
var
ration : single;
begin
ratio := width / height;

//我們 shading模範--Gouraud(smooth).
glShadeModel((GL_SMOOTH);

//挑揀出再殺掉.
glCullFace((GL_BACK);
glFrontFace((GL_CCW);
glEnable((GL_CULL_FACE);

//設定純顏色.
glClearColor((0,0,0,0);

//建立我們觀察孔.
glViewport( 0, 0, width, height );

{*
*改變成投影矩陣和裝置
*我們調查容量.
*}
glMatrixMode((GL_PROJECTION);
glLoadIdentity;
{*
*練習:
*用一向glFrustum呼叫代替這個.
*}
gluPerspective((60.0,比率,1.0,1024.0);
end;

var
width, height, bpp : integer;
flags : integer;
info : PSDL_VideoInfo;
begin
//關於目前影像設置的資訊.
info := nil;
//我們窗戶的度.
width := 0;
height := 0;
//在我們窗戶的小塊中彩色的深度.
bpp:=0;
//我們將變為SDL_SetVideoMode通過的旗幟.
lags := 0;

//首先預置SDL的影像子系統.
if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
begin
// Failed, exit.
MessageBox(0, PChar(Format('Video initialization failed : %s',
[SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
quit_tutorial( 1 );
end;

// Let's get some video information.
info := SDL_GetVideoInfo;

if( info <> nil ) then
begin
// This should probably never happen.
MessageBox(0, PChar(Format('Video query failed : %s', [SDL_GetError])),
'Error', MB_OK or MB_ICONHAND);
quit_tutorial( 1 );
end;

{*
* 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 or SDL_FULLSCREEN;

{*
* Set the video mode
*}
if ( SDL_SetVideoMode( width, height, bpp, flags ) = 0 ) then
begin
/*
* This could happen for a variety of reasons,
* including DISPLAY not being set, the specified
* resolution not being available, etc.
*/
MessageBox(0, PChar(Format('Video mode set failed : %s',
[SDL_GetError])), 'Error', MB_OK or MB_ICONHAND);
quit_tutorial( 1 );
end;

{*
* 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( true ) do
begin
// Process incoming events.
process_events;
// Draw the screen.
draw_screen;
end;

{*
* EXERCISE:
* Record timings using SDL_GetTicks() and
* and print out frames per second at program
* end.
*}

// Never reached.
exit;
end;