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

Win32 OpenGL編程(10) 視口變換

系統(tǒng) 2237 0

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

討論新聞組及文件

提要

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

1.確定照相機(jī)的位置的過(guò)程對(duì)應(yīng)于“視圖變換”(Viewing Transformations)

2.確定物體位置的過(guò)程對(duì)應(yīng)于“模型變換”(Modeling Transformations)

3.確定照相機(jī)放大倍數(shù)的過(guò)程對(duì)應(yīng)于“投影變換”(Projection Transformations)

4.確定照片大小的過(guò)程對(duì)應(yīng)于“視口變換”(Viewport Transformations)

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

視口變換

此變換應(yīng)該算是4種變換中最簡(jiǎn)單的了,在照相機(jī)比喻中我說(shuō)他是確認(rèn)照片大小,在實(shí)際中,確認(rèn)的是繪制的區(qū)域,當(dāng)然,我們以前沒(méi)有設(shè)定視口變換前,默認(rèn)是占據(jù)整個(gè)窗口的客戶區(qū)的。只有一個(gè)關(guān)鍵函數(shù)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.

無(wú)論前面進(jìn)行了多少處理,最終的圖像將映射到這個(gè)矩形中,默認(rèn)情況時(shí)占據(jù)整個(gè)窗口的客戶區(qū),在前面的所有例子中,(七巧板的例子除外)我們沒(méi)有接觸到視口變換,那么默認(rèn)就是窗口創(chuàng)建那一瞬間的大小,我們可以嘗試改變窗口大小,發(fā)現(xiàn)事實(shí)上圖形沒(méi)有變大,并且,位置也不再居中了,這個(gè)時(shí)候我們就需要進(jìn)行視口變換,調(diào)整視口。這里,因?yàn)橐郧坝衅咔砂宓睦恿?,也有原?lái)沒(méi)有使用的例子,我就不提供新的此用途的例子了,僅僅看兩個(gè)例子的區(qū)別。

未在窗口改變時(shí)重新設(shè)定視口的情況:

正常情況:

image

窗口縮小時(shí):圖像偏移了。

image

窗口放大時(shí):圖像不居中。

image

看七巧板中的例子:

因?yàn)橛幸韵麓a:

    
      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的作用,此時(shí),窗口大小改變時(shí),會(huì)重新設(shè)定視口,這樣,圖形將會(huì)隨著窗口大小改變而改變(這是大部分情況下我們需要的)

正常情況下:

image 窗口縮?。簣D形還是居中,因?yàn)榭v橫比的改變,導(dǎo)致圖形縱橫比也改變了。

image 窗口放大時(shí):圖形還是居中,因?yàn)榭v橫比的改變,導(dǎo)致圖形縱橫比也改變了。

image

上述七巧板的例子中,很好的演示了glViewport的作用,源代碼在以前就已經(jīng)提供了,這里不再說(shuō)了。但是,我們會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,就是窗口縱橫比改變的時(shí)候,圖形實(shí)際也改變了縱橫比導(dǎo)致變形了,這樣不太符合大部分情況下我們的想法,我們可以通過(guò)控制窗口的縱橫比來(lái)控制這一點(diǎn),(大部分情況下)或者直接通過(guò)控制glViewport參數(shù)的縱橫比也可以達(dá)到保證圖像不扭曲的目的。(但是圖形可能移位)

屏幕分割

玩過(guò)真三國(guó)無(wú)雙系列的玩家們不知道在同一臺(tái)機(jī)器上與戰(zhàn)友們?cè)⊙獖^斗過(guò)沒(méi)有,我是有過(guò),顯示時(shí),一個(gè)玩家在上面,一個(gè)在下面,在同一臺(tái)機(jī)器上不需要通過(guò)網(wǎng)絡(luò)就能享受聯(lián)機(jī)的樂(lè)趣,的確很有意思,事實(shí)上,我們通過(guò)視口變換連續(xù)繪制圖形兩次就能達(dá)到這樣的效果(我不知道真三國(guó)是否也是通過(guò)這樣的技術(shù)實(shí)現(xiàn)的),比如上述的七巧板的例子吧,我們想在屏幕上繪制4次,讓四個(gè)人同時(shí)玩,進(jìn)行對(duì)戰(zhàn),那么我們就可以這樣做:

    
      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這樣設(shè)計(jì)的好處,本身圖形的繪制很簡(jiǎn)單,在原點(diǎn)附近繪制一個(gè)標(biāo)準(zhǔn)的圖形而已,一種又一種變換后,卻可以產(chǎn)生于原來(lái)圖形千差萬(wàn)別的圖形,這一點(diǎn)有點(diǎn)像設(shè)計(jì)模式中的decorator模式.

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

呵呵,相當(dāng)happy吧,同一臺(tái)機(jī)子,4個(gè)人同時(shí)玩七巧板,(事實(shí)上,什么游戲都可以借鑒),什么?就一個(gè)鼠標(biāo)沒(méi)有辦法操作?暈?zāi)模悴粫?huì)插四個(gè)鼠標(biāo)?插四個(gè)鼠標(biāo)也沒(méi)有用?呵呵,推薦你看看我以前寫的關(guān)于多鼠標(biāo)的東西,4個(gè)人用4個(gè)鼠標(biāo)同時(shí)玩,不是什么不可能的^^以前魔獸好像有個(gè)4國(guó)戰(zhàn)爭(zhēng)的游戲地圖很流行,要是額外設(shè)計(jì),我們可以在同一臺(tái)機(jī)器上玩^^發(fā)揮大家的創(chuàng)意吧。

參考資料

1. 《 OpenGL Reference Manual 》,OpenGL參考手冊(cè)

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

3. 《Nehe OpenGL Tutorials》,Nehe著,在 http://nehe.gamedev.net/ 上可以找到教程及相關(guān)的代碼下載,(有PDF版本教程下載)Nehe自己還做了一個(gè)面向?qū)ο蟮目蚣?,作為演示程序?lái)說(shuō),這樣的框架非常合適。也有 中文版 ,各取所需吧。

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

本OpenGL系列其他文章

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

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

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

4. 《 Win32 OpenGL編程(4) 2D圖形基礎(chǔ)(顏色及坐標(biāo)體系進(jìn)階知識(shí))

5. 《 Win32 OpenGL編程(5)頂點(diǎn)數(shù)組詳細(xì)介紹

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

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

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

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

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

完整源代碼獲取說(shuō)明

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

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

Mercurial使用方法見(jiàn)《 分布式的,新一代版本控制系統(tǒng)Mercurial的介紹及簡(jiǎn)要入門

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

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

原創(chuàng)文章作者保留版權(quán) 轉(zhuǎn)載請(qǐng)注明原作者 并給出鏈接

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

Win32 OpenGL編程(10) 視口變換


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦?。?!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产婷婷高清在线观看免费 | 久久久99精品免费观看精品 | 成人a毛片 | 国内女高中生一级毛片 | 四虎国产永久在线观看 | 欧美成人香蕉在线观看 | 福利院肉动漫视频在线观看 | 日韩久久免费视频 | 岛国不卡 | 亚洲国产天堂久久九九九 | 五月婷网| 国产婷婷 | 在线播放亚洲精品富二代91 | 妞干网这里只有精品 | 久久99亚洲精品久久久久99 | 在线免费观看一级毛片 | 91在线永久| 免费亚洲视频 | 亚洲综合日韩在线亚洲欧美专区 | 久久久久久久久久久观看 | 黄色在线免费观看网站 | 亚洲国产天堂久久精品网 | 久久久免费观成人影院 | 免费视频久久看 | 亚洲成人高清在线 | 午夜精品在线视频 | 国产精品九九 | 国产亚洲区 | 色香欲综合网 | 国内精品久久久久影院蜜芽 | 日韩视频一区二区三区 | 2021最新久久久视精品爱 | 四虎永久在线精品影院 | 狼人综合伊人 | 国产啪爱视频精品免视 | 最新国产精品亚洲 | 欧美一级永久免费毛片在线 | 激情婷婷综合 | 日本一级特黄视频 | 亚洲高清视频一区 | 变态 调教 视频 国产九色 |