Delphi下OpenGL2d繪圖(06)-畫圖(多視窗、多視圖、多個DC)

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   使用   

一、前言

在學習OpenGL的過程中,發現很多函數都是全域的。前面幾章中都是在一個視窗DC中畫圖,那麼要在多個視窗畫圖,需要怎麼處理呢?網上方法有多種,這裡採用其中一種,利用wglMakeCurrent函數來切換不同視窗,以達到多視窗同時喧染的目的。

二、準備

每個視窗與OpenGL綁定時,都通過以下幾個過程進行:

1.擷取視窗控制代碼Handle/HWND(在TWinControl繼承下來的類中,都可以通過TWinControl.Handle獲得,MFC的視窗可以通過CWnd::GetSafeHwnd()獲得)

2.通過控制代碼擷取裝置情境HDC(通過API GetDC()擷取)

3.通過裝置情境HDC擷取OpenGL的HGLRC(通過OpenGL的wglCreateContext()獲得)

當然,在程式銷毀時記得釋放相應的HGLRC與視窗DC。通過以上的對應關係,可以把這些資訊儲存在數組中。以四個視窗為例,我建了這樣幾個數組:

    FDC: array[0..3] of HDC;    FHRC: array[0..3] of HGLRC;    FHwnd: array[0..3] of THandle;

三、初始化

本例以多個TPanel為例代替多個視窗,以上三個數組進行初始化。建立了一個inidc()的方法,在視窗的OnCreate時調用,目的是初始化陣列變數的值

procedure TForm1.FormCreate(Sender: TObject);begin  Fbmpindex := 0;  // 對多個視窗進行初始化  inidc(0, Pnl1.Handle);  inidc(1, Pnl2.Handle);  inidc(2, Pnl3.Handle);  inidc(3, Pnl4.Handle);end;

下面的inidc的代碼

procedure TForm1.inidc(i: Integer; hform: THandle);var pfd:TPIXELFORMATDESCRIPTOR;  pixelFormat: Integer;begin  With pfd do  begin    nSize := sizeof(TPIXELFORMATDESCRIPTOR); // size    nVersion := 1; // version    dwFlags := PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER; // support double-buffering    iPixelType := PFD_TYPE_RGBA; // color type    cColorBits := 24; // preferred color depth    cRedBits := 0;    cRedShift := 0; // color bits (ignored)    cGreenBits := 0;    cGreenShift := 0;    cBlueBits := 0;    cBlueShift := 0;    cAlphaBits := 0;    cAlphaShift := 0; // no alpha buffer    cAccumBits := 0;    cAccumRedBits := 0; // no accumulation buffer,    cAccumGreenBits := 0; // accum bits (ignored)    cAccumBlueBits := 0;    cAccumAlphaBits := 0;    cDepthBits := 16; // depth buffer    cStencilBits := 0; // no stencil buffer    cAuxBuffers := 0; // no auxiliary buffers    iLayerType := PFD_MAIN_PLANE; // main layer    bReserved := 0;    dwLayerMask := 0;    dwVisibleMask := 0;    dwDamageMask := 0;  end;  FDC[i] := GetDC(hform);  FHwnd[i] := hform;  pixelFormat := ChoosePixelFormat(FDC[i], @pfd);  if pixelFormat = 0 then    Exit;  if not SetPixelFormat(FDC[i], pixelFormat, @pfd) then    Exit;  FHRC[i] := wglCreateContext(FDC[i]);  wglMakeCurrent(FDC[i], FHRC[i]);  // 設定背景色為 黑色 參數為 RGBA  glClearColor(0, 0, 0, 0);end;

四、繪製

這裡修改一下前面幾章中的Draw函數,用於支援多視窗的繪製,代碼如下:

procedure TForm1.Draw(i: Integer);var  Bmp: TBitmap;  texture: GLuint;  l, t, w, h: Integer;  rc: TRect;begin  // 重新設定顯示地區  wglMakeCurrent(FDC[i], FHRC[i]);  // 重新計算並設定顯示地區大小  GetWindowRect(fhwnd[i], rc);  w := rc.Right - rc.Left;  h := rc.Bottom - rc.Top;  glMatrixMode(GL_PROJECTION);  glLoadIdentity;  glViewPort(0, 0, w, h);  gluOrtho2D(0, w, h, 0);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity;  // 只是為了顯示多個圖片,不是必須的  inc(Fbmpindex);  Bmp := TBitmap.Create;  Bmp.LoadFromFile(ExtractFilePath(ParamStr(0)) + IntToStr(Fbmpindex mod 3) + ‘.bmp‘);  // 建立紋理地區  glGenTextures(1, @texture);  // 綁定紋理地區  glBindTexture(GL_TEXTURE_2D, texture);  // 使用位元影像建立映像紋理  glTexImage2D(    GL_TEXTURE_2D,            // 紋理是一個2D紋理 GL_TEXTURE_2D    0,                        // 映像的詳細程度 預設 0    3,                        // 資料的成分數。因為映像是由紅,綠,藍三種組成 預設3    Bmp.Width,                // 紋理的寬度    Bmp.Height,               // 紋理的高度    0,                        // 邊框的值 預設 0    GL_BGR_EXT,               // 資料格式 bmp使用 bgr    GL_UNSIGNED_BYTE,         // 組成映像的資料是無符號位元組類型的    Bmp.ScanLine[Bmp.Height - 1] // DIB資料指標  );  // 下面兩行是讓opengl在放大原始的紋理大(GL_TEXTURE_MAG_FILTER)或縮小原始紋理(GL_TEXTURE_MIN_FILTER)時OpenGL採用的濾波方式。  // GL_LINEAR 使用線性濾波,可以把圖片處理處平滑,但需要更多的記憶體與CPU  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  // 線形濾波  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 線形濾波  // 以下是繪圖,利用一個四邊形,繪製圖片    // 啟用紋理映射  if glIsEnabled(GL_TEXTURE_2D) = 0 then    glEnable(GL_TEXTURE_2D);  // 清空緩衝區  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    l := 10;  t := 10;  w := 100 + (i * 50); // 放大為200*200的圖片  // 選擇紋理 如果情境中使用多個紋理,不能在glBegin() 和 glEnd() 之間綁定紋理  glBindTexture(GL_TEXTURE_2D, texture);  glBegin(GL_QUADS);  // glTexCoord2f 的第一個參數是X座標。  // 0.0是紋理的左側。 0.5是紋理的中點, 1.0是紋理的右側。  // glTexCoord2f 的第二個參數是Y座標。  // 0.0是紋理的底部。 0.5是紋理的中點, 1.0是紋理的頂部。  glTexCoord2f(0, 1);  glVertex2f(l, t);  glTexCoord2f(1, 1);  glVertex2f(l + w, t);  glTexCoord2f(1, 0);  glVertex2f(l + w, t + w);  glTexCoord2f(0, 0);  glVertex2f(l, t + w);  glEnd();  Bmp.Free;  SwapBuffers(FDC[i]);end;

上面的畫圖片的代碼,如果覺得看起來複雜,可以用以下簡單點的代碼:

procedure TForm1.DrawSimple(i: Integer);var  l, t, w, h: Integer;  rc: TRect;begin  // 重新設定顯示地區  wglMakeCurrent(FDC[i], FHRC[i]);  // 重新計算並設定顯示地區大小  GetWindowRect(fhwnd[i], rc);  w := rc.Right - rc.Left;  h := rc.Bottom - rc.Top;  glMatrixMode(GL_PROJECTION);  glLoadIdentity;  glViewPort(0, 0, w, h);  gluOrtho2D(0, w, h, 0);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity;  // 清空緩衝區  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  // 設定四邊形的顏色  glColor3f(1, 0.5, 0);  // 繪製第一個多邊形  l := 10;  t := 10;  w := 64 + (i - 2) * 50;  glBegin(GL_QUADS);  glVertex2f(l, t);  glVertex2f(l + w, t);  glVertex2f(l + w, t + w);  glVertex2f(l, t + w);  glEnd();  SwapBuffers(FDC[i]);end;

為了方便示範,這裡用一個定時器TTimer代替以前在視窗的OnPaint畫圖,定時器下的代碼如下:

procedure TForm1.tmr1Timer(Sender: TObject);begin  Draw(0);  Draw(1);  DrawSimple(2);  DrawSimple(3);end;

五、釋放

最後記得釋放資源,Delphi中基本上申請的資源都要回收,new->delete/dispose、get->release、create->destroy,簡單的說,建立(create)的要銷毀(destroy),借(get)的要還(release)。

procedure TForm1.FormDestroy(Sender: TObject);var  i: Integer;begin  for i := 0 to 4 - 1 do  begin    wglMakeCurrent(FDC[i], FHRC[i]);    wglDeleteContext(FHRC[i]);    ReleaseDC(fhwnd[i], FDC[i]);  end;end;

效果如下:

源碼下載:OpenGL_06.zip

2014-07-17 by lin

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.