亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Win32 OpenGL編程(10) 視口變換

系統 1879 0

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

提要

在前文(系列文章(7),以下簡稱XO7,系列其他文章類似)中的照相機比喻中提到了4種3D變換,如下:

1.確定照相機的位置的過程對應于“視圖變換”(Viewing Transformations)

2.確定物體位置的過程對應于“模型變換”(Modeling Transformations)

3.確定照相機放大倍數的過程對應于“投影變換”(Projection Transformations)

4.確定照片大小的過程對應于“視口變換”(Viewport Transformations)

XO7中我們講的是第一種變換視圖變換,即改變觀察者本身的位置,視角等的變換效果,XO8中講的是第二種變換模型變換,XO9中講的是投影變換,本文開始講解最后一個變換,視口變換。

視口變換

此變換應該算是4種變換中最簡單的了,在照相機比喻中我說他是確認照片大小,在實際中,確認的是繪制的區域,當然,我們以前沒有設定視口變換前,默認是占據整個窗口的客戶區的。只有一個關鍵函數glViewport,而且較易理解:

OpenGL Programming Guide 》:

glViewport — set the viewport
C Specification
void glViewport( GLint x,
GLint y,
GLsizei width,
GLsizei height);
Parameters

x, y

Specify the lower left corner of the viewport rectangle,
in pixels. The initial value is (0,0).
width, height

Specify the width and height
of the viewport.
When a GL context is first attached to a window,
width and height are set to the dimensions of that
window.

無論前面進行了多少處理,最終的圖像將映射到這個矩形中,默認情況時占據整個窗口的客戶區,在前面的所有例子中,(七巧板的例子除外)我們沒有接觸到視口變換,那么默認就是窗口創建那一瞬間的大小,我們可以嘗試改變窗口大小,發現事實上圖形沒有變大,并且,位置也不再居中了,這個時候我們就需要進行視口變換,調整視口。這里,因為以前有七巧板的例子了,也有原來沒有使用的例子,我就不提供新的此用途的例子了,僅僅看兩個例子的區別。

未在窗口改變時重新設定視口的情況:

正常情況:

image

窗口縮小時:圖像偏移了。

image

窗口放大時:圖像不居中。

image

看七巧板中的例子:

因為有以下代碼:

    
      void 
    
    
      ReShape
    
    
(
    
      unsigned 
    
    
      auWidth
    
    
, 
    
      unsigned 
    
    
      auHeight
    
    
)
{
    
    
      glViewport
    
    
(0, 0, 
    
      auWidth
    
    
, 
    
      auHeight
    
    
);
}
  

    
      // FUNCTIONS //////////////////////////////////////////////

    
    
      LRESULT CALLBACK WindowProc
    
    
(
    
      HWND hwnd
    
    
, 
                            
    
      UINT msg
    
    
, 
                            
    
      WPARAM wparam
    
    
, 
                            
    
      LPARAM lparam
    
    
)
{
    
    
      // this is the main message handler of the system
    
    
    
      PAINTSTRUCT        ps
    
    
;        
    
      // used in WM_PAINT
    
    
    
      HDC                hdc
    
    
;    
    
      // handle to a device context

    // what is the message 
    
    
    
      switch
    
    
(
    
      msg
    
    
)
    {    
    
    
      case 
    
    
      WM_CREATE
    
    
: 
        {
            
    
      // do initialization stuff here
            // return success
            
    
    
      return
    
    
(0);
        } 
    
      break
    
    
;

    
    
      case 
    
    
      WM_PAINT
    
    
: 
        {
            
    
      // simply validate the window 
            
    
    
      hdc 
    
    
= 
    
      BeginPaint
    
    
(
    
      hwnd
    
    
,&
    
      ps
    
    
);     

            
    
      // end painting
            
    
    
      EndPaint
    
    
(
    
      hwnd
    
    
,&
    
      ps
    
    
);

            
    
      // return success
            
    
    
      return
    
    
(0);
        } 
    
      break
    
    
;

    
    
      case 
    
    
      WM_DESTROY
    
    
: 
        {
            
    
      // kill the application, this sends a WM_QUIT message 
            
    
    
      PostQuitMessage
    
    
(0);

            
    
      // return success
            
    
    
      return
    
    
(0);
        } 
    
      break
    
    
;
    
    
      case 
    
    
      WM_SIZE
    
    
:
        {
            
    
      ReShape
    
    
(
    
      LOWORD
    
    
(
    
      lparam
    
    
), 
    
      HIWORD
    
    
(
    
      lparam
    
    
));
        }
    
    
      default
    
    
:
    
      break
    
    
;

    } 
    
      // end switch

    // process any messages that we didn't take care of 
    
    
    
      return 
    
    
(
    
      DefWindowProc
    
    
(
    
      hwnd
    
    
, 
    
      msg
    
    
, 
    
      wparam
    
    
, 
    
      lparam
    
    
));

} 
    
      // end WinProc
    
  

注意reshape的作用,此時,窗口大小改變時,會重新設定視口,這樣,圖形將會隨著窗口大小改變而改變(這是大部分情況下我們需要的)

正常情況下:

image 窗口縮?。簣D形還是居中,因為縱橫比的改變,導致圖形縱橫比也改變了。

image 窗口放大時:圖形還是居中,因為縱橫比的改變,導致圖形縱橫比也改變了。

image

上述七巧板的例子中,很好的演示了glViewport的作用,源代碼在以前就已經提供了,這里不再說了。但是,我們會發現一個問題,就是窗口縱橫比改變的時候,圖形實際也改變了縱橫比導致變形了,這樣不太符合大部分情況下我們的想法,我們可以通過控制窗口的縱橫比來控制這一點,(大部分情況下)或者直接通過控制glViewport參數的縱橫比也可以達到保證圖像不扭曲的目的。(但是圖形可能移位)

屏幕分割

玩過真三國無雙系列的玩家們不知道在同一臺機器上與戰友們浴血奮斗過沒有,我是有過,顯示時,一個玩家在上面,一個在下面,在同一臺機器上不需要通過網絡就能享受聯機的樂趣,的確很有意思,事實上,我們通過視口變換連續繪制圖形兩次就能達到這樣的效果(我不知道真三國是否也是通過這樣的技術實現的),比如上述的七巧板的例子吧,我們想在屏幕上繪制4次,讓四個人同時玩,進行對戰,那么我們就可以這樣做:

    
      void 
    
    
      ReShape
    
    
(
    
      unsigned 
    
    
      auWidth
    
    
, 
    
      unsigned 
    
    
      auHeight
    
    
)
{
    
    
      WindowWidth 
    
    
= 
    
      auWidth
    
    
;
    
    
      WindowHeight 
    
    
= 
    
      auHeight
    
    
;

}


    
      // All Scene Show code 

    
    
      void 
    
    
      SceneShow
    
    
(
    
      GLvoid
    
    
)        
{
    
    
      glClear
    
    
(
    
      GL_COLOR_BUFFER_BIT
    
    
);    

    
    
      // left bottom
    
    
    
      glViewport
    
    
(0, 0, 
    
      WindowWidth
    
    
/2, 
    
      WindowHeight
    
    
/2);

    
    
      gTriBTop
    
    
.
    
      Draw
    
    
();
    
    
      gTriBRight
    
    
.
    
      Draw
    
    
();
    
    
      gTriSLeft
    
    
.
    
      Draw
    
    
();
    
    
      gRectangle
    
    
.
    
      Draw
    
    
();
    
    
      gTriSMid
    
    
.
    
      Draw
    
    
();
    
    
      gTriMLeft
    
    
.
    
      Draw
    
    
();
    
    
      gParal
    
    
.
    
      Draw
    
    
();

    
    
      // right bottom
    
    
    
      glViewport
    
    
(
    
      WindowWidth
    
    
/2, 0, 
    
      WindowWidth
    
    
/2, 
    
      WindowHeight
    
    
/2);

    
    
      gTriBTop
    
    
.
    
      Draw
    
    
();
    
    
      gTriBRight
    
    
.
    
      Draw
    
    
();
    
    
      gTriSLeft
    
    
.
    
      Draw
    
    
();
    
    
      gRectangle
    
    
.
    
      Draw
    
    
();
    
    
      gTriSMid
    
    
.
    
      Draw
    
    
();
    
    
      gTriMLeft
    
    
.
    
      Draw
    
    
();
    
    
      gParal
    
    
.
    
      Draw
    
    
();

    
    
      // left top 
    
    
    
      glViewport
    
    
(0 , 
    
      WindowHeight
    
    
/2, 
    
      WindowWidth
    
    
/2, 
    
      WindowHeight
    
    
/2);

    
    
      gTriBTop
    
    
.
    
      Draw
    
    
();
    
    
      gTriBRight
    
    
.
    
      Draw
    
    
();
    
    
      gTriSLeft
    
    
.
    
      Draw
    
    
();
    
    
      gRectangle
    
    
.
    
      Draw
    
    
();
    
    
      gTriSMid
    
    
.
    
      Draw
    
    
();
    
    
      gTriMLeft
    
    
.
    
      Draw
    
    
();
    
    
      gParal
    
    
.
    
      Draw
    
    
();

    
    
      // right top 
    
    
    
      glViewport
    
    
(
    
      WindowWidth
    
    
/2 , 
    
      WindowHeight
    
    
/2, 
    
      WindowWidth
    
    
/2, 
    
      WindowHeight
    
    
/2);

    
    
      gTriBTop
    
    
.
    
      Draw
    
    
();
    
    
      gTriBRight
    
    
.
    
      Draw
    
    
();
    
    
      gTriSLeft
    
    
.
    
      Draw
    
    
();
    
    
      gRectangle
    
    
.
    
      Draw
    
    
();
    
    
      gTriSMid
    
    
.
    
      Draw
    
    
();
    
    
      gTriMLeft
    
    
.
    
      Draw
    
    
();
    
    
      gParal
    
    
.
    
      Draw
    
    
();

    
    
      glFlush
    
    
();
}  
  

顯示效果:

image

注意上述代碼中,我們的具體的顯示代碼只有一份,顯示代碼中并不知道自己繪制了幾份,繪制在什么地方,這也就是OpenGL這樣設計的好處,本身圖形的繪制很簡單,在原點附近繪制一個標準的圖形而已,一種又一種變換后,卻可以產生于原來圖形千差萬別的圖形,這一點有點像設計模式中的decorator模式.

為節省篇幅僅貼出關鍵片段,完整源代碼見我博客源代碼的2009-10-29/JTFourTangram 目錄,獲取方式見文章最后關于獲取博客完整源代碼的說明。

呵呵,相當happy吧,同一臺機子,4個人同時玩七巧板,(事實上,什么游戲都可以借鑒),什么?就一個鼠標沒有辦法操作?暈哪,你不會插四個鼠標?插四個鼠標也沒有用?呵呵,推薦你看看我以前寫的關于多鼠標的東西,4個人用4個鼠標同時玩,不是什么不可能的^^以前魔獸好像有個4國戰爭的游戲地圖很流行,要是額外設計,我們可以在同一臺機器上玩^^發揮大家的創意吧。

參考資料

1. 《 OpenGL Reference Manual 》,OpenGL參考手冊

2. 《OpenGL 編程指南》(《 OpenGL Programming Guide 》),Dave Shreiner,Mason Woo,Jackie Neider,Tom Davis 著,徐波譯,機械工業出版社

3. 《Nehe OpenGL Tutorials》,Nehe著,在 http://nehe.gamedev.net/ 上可以找到教程及相關的代碼下載,(有PDF版本教程下載)Nehe自己還做了一個面向對象的框架,作為演示程序來說,這樣的框架非常合適。也有 中文版 ,各取所需吧。

4. 《OpenGL入門學習》 ,eastcowboy著,這是我在網上找到的一個比較好的教程,較為完善,而且非常通俗。這是第一篇的地址: http://bbs.pfan.cn/post-184355.html

本OpenGL系列其他文章

1. Win32 OpenGL 編程(1)Win32下的OpenGL編程必須步驟

2. 《 Win32 OpenGL編程(2) 尋找缺失的OpenGL函數

3. 《 Win32 OpenGL編程(3) 基本圖元(點,直線,多邊形)的繪制

4. 《 Win32 OpenGL編程(4) 2D圖形基礎(顏色及坐標體系進階知識)

5. 《 Win32 OpenGL編程(5)頂點數組詳細介紹

6.《 Win32 OpenGL編程(6) 踏入3D世界

7.《 Win32 OpenGL編程(7) 3D視圖變換——真3D的關鍵

8.《 Win32 OpenGL編程(8) 3D模型變換及其組合應用

9.《 Win32 OpenGL編程(9) 投影變換

應用舉例:《 Win32 OpenGL編程系列 2D例子 -- 七巧板圖形繪制

完整源代碼獲取說明

由于篇幅限制,本文一般僅貼出代碼的主要關心的部分,代碼帶工程(或者makefile)完整版(如果有的話)都能用Mercurial在Google Code中下載。文章以博文發表的日期分目錄存放,請直接使用Mercurial克隆下庫:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法見《 分布式的,新一代版本控制系統Mercurial的介紹及簡要入門

要是僅僅想瀏覽全部代碼也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

原創文章作者保留版權 轉載請注明原作者 并給出鏈接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

Win32 OpenGL編程(10) 視口變換


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 婷婷免费在线 | 午夜大片免费男女爽爽影院久久 | 国产精品夜色7777青苹果 | 免费看曰批女人爽的视频网址 | 一级做受视频免费是看美女 | 天天做夜夜操 | 久久香焦| 性成人动作片在线看 | 色网在线免费观看 | 日本在线网址 | 青青青国产深夜福利视频 | 国产性大片黄在线观看在线放 | 91精品日本久久久久久牛牛 | 日本一区二区三区四区在线观看 | 日本免费一二三区 | 熊出没之重启未来免费观看 | 亚洲一级毛片免费看 | 成人区精品一区二区毛片不卡 | 色色视频网 | 欧美成人免费香蕉 | 99热久久国产精品这里小说 | 91精品视频在线免费观看 | 在线观看亚洲精品专区 | 国产亚洲男人的天堂在线观看 | 国产一级aaa全黄毛片 | 99久久综合狠狠综合久久一区 | 午夜精品久久久久久 | 99久久一区二区精品 | 亚洲精品不卡午夜精品 | 在线视频一区二区三区四区 | 91久久精品都在这里 | 亚洲毛片网 | 羞羞色院91蜜桃在线观看 | 天天艹夜夜 | 天天干天天操天天做 | 国产欧美亚洲精品 | 亚洲特级毛片 | 天天射夜夜爱 | 成人国产亚洲欧美成人综合网 | 拍拍拍无挡视频免费观看1000 | 一区二区三区国产精品 |