青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

醬壇子

專注C++技術 在這里寫下自己的學習心得 感悟 和大家討論 共同進步(歡迎批評!!!)

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  66 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

公告

王一偉 湖南商學院畢業 電子信息工程專業

常用鏈接

留言簿(19)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 388842
  • 排名 - 64

最新隨筆

最新評論

閱讀排行榜

評論排行榜

對作者心血表示感謝,先附上原文:http://www.86vr.com/teach/cursor/200410/3841.html
實時3D繪圖的陰影效果
目 錄

  1 平面陰影
  2 體積陰影


附帶的源程序(91KB)

  在目前的實時3D繪圖中,要做出真實的陰影效果,是很不容易的。因為陰影是因物體遮住光源所產生的,因此,要做出正確的陰影效果,就需要對整個場景做處理,這樣才能判斷出哪些物體被哪些物體遮住了。

  不過,目前的3D硬件,并不容易進行這類的測試,因為資料量和工作量都太大了。不過,這并不表示使用現在的3D硬件就無法做出陰影。現在已經有很多方法是適合用在目前的3D硬件上面,可以產生效果不錯的陰影。本文會就一些常用的方法,做簡單的介紹。


1、平面陰影

  目前常用的方法,幾乎都是把陰影看成是“物體投射到其它表面”來處理。在光源是平行光的時候(例如,太陽光),可以看成是物體把陰影“投射”到另一個表面上,如下圖所示:

  如果場景中只有一個重要的光源(即最強的光源),那可以假設只有這個光源會產生明顯的陰影。以平行光源來說,要把陰影“投射”到一個平面上,就是一件相當容易的事。

  設空間有一點V,平行光源的方向是L,要投射陰影的平面是P,那么,存在一常數k使

  成立,如下圖(V、L、和 P均為四維向量,表示一個三維的齊次坐標:homogeneous coordinate):

  解上式得

  空間中的點V投影到平面P的位置是V+kP。對一個3D模型(model)的每個頂點都代入這個式子,就可以得到投影的結果了。不過,因為目前的3D硬件都是以4×4的矩陣來做變換,所以如果能把投影的動作寫成一個矩陣,就會方便很多。

  設V = <Vx, Vy, Vz, 1>,L = <Lx, Ly, Lz, 0>,P = <a, b, c, d>;展開前面的式子,會發現k有一個分母:

  因此這個式子會有點復雜。不過,因為在OpenGL中的向量都是齊次坐標(homogeneous coordinate),所以可以先把分母提出來,放到w中。對Vx展開得到:

整理一下得到

  這樣就變成向量內積的形式,可以放到矩陣中。對Vy和Vz做同樣的動作,再加上放到w的分母部分,就可以得到下面的矩陣:

  因此,理論上,要畫陰影時,把MODELVIEW矩陣設成上面的矩陣,畫出物體,就會是陰影的樣子。

  上面討論的是以平行光源為主。如果光源是點光源,也可以用類似的方法來做。

  這個方法可以對任何平面做出陰影的效果。如果有多個平面,可以分別對每個平面都做一次。不過,這個方法顯然是沒辦法把陰影投影到曲面上。所以,這個方法通常稱為平面陰影(planar shadow)。

  理論的部分已經討論完了。不過,實作的時候,還有一些細節部分是需要特別注意的。

  首先,如果真的直接用上面的方法來做,那做出來的結果可能會像這樣:

  這是因為畫了圖中的地板之后,再畫黑色的陰影時,會和地板產生所謂的Z fighting現象,也就是陰影的一部分的Z值較地板的Z值小,所以會畫出來,但是有些部分的Z值則可能比地板的Z值大,所以就沒畫出來了。這種現象會使得陰影變得破碎不完整。

  現在的3D硬件通常提供一個叫多邊形偏移(polygon offset)的功能,用來解決Z fighting的問題。多邊形偏移的原理,是在畫一個物體時,要求把它的Z值進行一個小的調整。例如,在上面的例子中,我們可以把陰影的Z值減一個小的數字,這樣就可以避免Z fighting的現象。

  處理掉Z fighting后,再來是第二個問題:

  上圖中,陰影跑到地板的外面去了。這里需要一個方法,把陰影切到地板的范圍內。這個例子中,地板的邊界是直線,所以可以用user defined clip planes來做。不過,如果地板是奇怪的形狀,就需要別的方法。

  而且,光是把陰影切到地板的范圍內是不夠的。通常陰影是用blending的方式畫上去的。如果一個物體的形狀比較復雜,那有些地方可能會blend兩次或更多次。這樣會讓陰影看起來不是同一個顏色,即有些地方顏色較深而有些地方較淺。

  現在的3D硬件多半支持模板緩沖區(stencil buffer)。模板緩沖區是一個用來“做記號”的緩沖區。通常模板緩沖區可以存放1 bits到8 bits不等的數字,不同的硬件支持的大小會不一樣。目前的3D硬件通常把模板緩沖區和Z buffer放在一起。例如,它可能支持15 bits的Z buffer加上1 bit的模板緩沖區;或是支持24 bits的Z buffer加上8 bit的模板緩沖區。因此,通常模板緩沖區的測試是和Z測試一起做的,也就是在使用Z buffer時,模板緩沖區可說是“免費”的。

  在我們的例子中,可以先把模板緩沖區(stencil buffer)全清為0。在畫地板之前,把模板緩沖區設定為“當Z測試通過時,把模板的值設為1”。這樣一來,畫完地板之后,地板所占有的那些像素的模板值就都會是1,其它的地方還是0。現在,把模板緩沖區設定成“當Z測試通過時,若模板的值為1才畫,且將模板的值設為0”。然后開始畫陰影。這樣畫出來的陰影,一定會在地板的范圍內,而且每個像素只會被畫一次,不會出現blend兩次的情形。

  如果有多個平面要投影,可以為每個平面指定不同的模板(stencil)值。不過,如果模板緩沖區(stencil buffer)只有1 bit,那就沒辦法了。這時,可能就需要在畫下一個平面之前,先把模板緩沖區清掉,這樣會花很多時間。

  下圖是一個完整的例子:

  參考程序你可以去試驗。這個程序需要至少2 bits的模板緩沖區(stencil buffer)支持。

  平面陰影(Planar shadow)就差不多是這個樣子了。平面陰影的好處是簡單、容易做,而且在投影面不多的時候,速度很快。但是,當投影面變多時,或是物體很復雜時,速度很快就會變得很慢,因為對每個平面都需要把投影的物體再畫一次。而且,它只能投影在平面上,對于不規則的表面則完全沒辦法。

  還有一些別的方法可以產生陰影的效果。后面還會再討論一些產生陰影的方式,都可以投影在任何不規則的表面上。

2、體積陰影

  前面所介紹的方法,即平面陰影(Planar shadow),只適用于平面上。但是,除了少數的情形之外,絕大多數的情形下,根本無法預測陰影會被投射在什么樣的表面上。所以,我們需要自由度更高的方法。

  在這里介紹一個較為靈活的方法,它可以將陰影投射在不規則的表面上。這個方法稱為體積陰影(Volumetric Shadow)。這個方法的動點在于,它并不是利用“把物體投影到表面”的方式來產生陰影,而是去找出場景中,有哪些像素是在陰影中。也就是說,想象一個物體擋住光時,在物體的后面會形成一個大的“陰影錐”。很明顯的,若一個像素在“陰影錐”之中,那它就是在陰影之中。如下圖所示:

  上圖中的紅色球體,在受光照后,在后方產生一個“陰影錐”,即Shadow Volume,而這個“陰影錐”和灰色平面的交集,就是陰影會出現的地方。

  所以,基本上體積陰影(Volumetric Shadow)的原理是很簡單的。不過,要真正實作又是另一回事。為了簡單起見,這里先以一個簡單的三角形開始。目前的3D繪圖幾乎都是以三角形為基礎,所以從三角形開始,應該是很適當的。

  現在,假設有一個已經繪制完成的3D場景。因為使用Z buffer的關系,對每一個像素而言,都有一個相對的Z值,即表示該像素和觀察者的距離的值。如果現在有一個三角面,把陰影投射到這個3D場景中,并畫出這個三角面的“陰影錐”。因為物體是一個三角形,所以它的“陰影錐”也是一個三角錐。這時,要如何知道3D場景中,有哪些像素是和這個三角錐有交集?

  其實方法很簡單。想象許多射線,由觀察者射向每個像素。如果射線和“陰影錐”完全沒有交集,它所對應的像素當然就不會和“陰影錐”有交集。不過,即使是射線和“陰影錐”有交集,并不一定表示該像素就一定和“陰影錐”有交集,因為射線可能會射入“陰影錐”后又射出。所以,只有在射線射入“陰影錐”之后,在離開“陰影錐”之前就遇到其對應的像素時,才表示這個像素和“陰影錐”有交集。下圖顯示出各種不同的情形:

  上圖中的(1)和(2)都是面對觀察者的面,所以它們所涵蓋的像素,就是“射線會射入陰影錐”的像素。而(3)則是背對觀察者的面,所以它所涵蓋的像素是“射線會離開陰影錐”的像素。所以,會和陰影錐有交集的像素,就是(1)+(2)-(3)的那些像素,也就是陰影所在的位置。

  不過,要怎么在一般的3D繪圖硬件中,得到(1)+(2)-(3)的結果呢?和平面陰影(Planar shadow)一樣,這需要模板緩沖區(stencil buffer)。在OpenGL和Direct3D中的模板緩沖區都可以讓它進行“加一”和“減一”的動作。所以,只要把模板緩沖區設定成:在繪制(1)和(2)的面時,讓模板緩沖區加一;而在繪制(3)的面時,讓 模板緩沖區減一。這樣一來,在畫完(1)~(3)時,那些模板(stencil)值不為0的像素就是陰影了。最后,把所有模板不為0的像素利用alpha blending的方式,使其亮度降低,就可以達到繪制陰影的效果。

  上面的例子是用一個三角面。對于比較復雜的物體,其原理還是一樣的。當物體是由許多三角面組成時,可以把所有面對光源的三角面都進行上面的動作,就可以產生陰影。不過,這樣有個缺點:因為很多三角面的邊是接在一起的,所以這樣做會十分浪費時間。要提高效率其實也很容易。在繪制“陰影錐”的時候,若有一個邊是被兩個三角面所共享,那就表示這是一個“內部”的邊,在繪制“陰影錐”的時候,就可以不用去畫這個邊。這樣就可以省下不少的時間。

  這個方法適用于非常復雜的物體。不過,它還是可能會遇上一些問題。一個情形是,如果觀察者在“陰影錐”的內部,會發生一些麻煩的情形。不過,對大部分的情形來說,只要將模板緩沖區(stencil buffer)設定成“減到0就停止”,即0 - 1 = 0,就可以解決。當然這無法解決所有的問題,不過通常已經夠好了。另外,如果物體不是 convex(即“凸”的),那可能會出現“射線重復進入陰影錐”的情形。這種情形并不會有問題,不過模板緩沖區就需要比較多bit才不會出錯。一般來說,4 bits就已經可以處理絕大多數的物體的。

  下面的畫面是體積陰影(Volumetric Shadow)的結果,是由DirectX 8 SDK中的一個示范程序所產生的。這個程序的結構并不復雜,所以有興趣的話,可以自行參考它的原始碼。

  這個方法比平面陰影(Planar shadow)更能適用于不同的場景。不過,它當然也有缺點。最主要的缺點是在于它的復雜度。要做出有效率的“陰影錐”,需要對物體做相當麻煩的處理,基本上就是要找出物體在某個方向的“外緣”(即silhouette)。雖然這并不太難做,但是還是需要花費相當的CPU時間去處理。另外,為所有的物體繪制出其“陰影錐”,需要相當大量的填充率(fill rate)和內存頻寬。若是延后渲染(deferred renderer),例如圖素渲染(tile renderer)則影響不會這么大,特別是圖素渲染可以支持一些特別的功能,來加速體積陰影(Volumetric Shadow)的動作。

  基本上,體積陰影(Volumetric Shadow)的效果,一般來說都不錯。最主要的缺點則是在效率方面,特別是當物體的復雜度和數量增加時,CPU需要的工作量會大增,是較為不理想的。后面會再介紹一些速度更快的方法。
posted on 2009-03-27 11:11 @王一偉 閱讀(2847) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜精品国产精品大乳美女| 蘑菇福利视频一区播放| 亚洲激情黄色| 免费欧美电影| 一区二区三区高清不卡| 一本到高清视频免费精品| 欧美三级日韩三级国产三级| 亚洲视频在线免费观看| 亚洲欧美日韩天堂| 在线精品高清中文字幕| 亚洲福利视频网站| 国产精品成人一区二区艾草| 欧美在线亚洲在线| 久久久在线视频| 在线一区视频| 欧美自拍丝袜亚洲| 亚洲精品国产系列| 亚洲伊人久久综合| 亚洲国产欧美一区二区三区同亚洲 | 久久精品99久久香蕉国产色戒| 影音先锋亚洲精品| 99re热这里只有精品视频| 国产精品亚洲一区| 亚洲国产另类久久精品| 国产精品视频午夜| 亚洲激情国产| 韩国女主播一区| 一区二区三区视频在线播放| 激情六月婷婷久久| 亚洲视频欧洲视频| 亚洲欧洲日产国码二区| 亚洲欧美日韩精品综合在线观看| 亚洲国产专区| 欧美一区二区三区日韩| 亚洲视频日本| 欧美国产精品久久| 久久字幕精品一区| 国产色综合久久| 日韩特黄影片| 亚洲日本va在线观看| 午夜在线视频观看日韩17c| a4yy欧美一区二区三区| 久久视频在线视频| 久久久久久久久综合| 欧美亚韩一区| 亚洲精品久久久一区二区三区| 国产综合久久久久久| 亚洲一区二区精品在线| 一本色道久久综合狠狠躁篇的优点| 久久久久欧美精品| 久久亚洲私人国产精品va媚药 | 久久精品一二三区| 欧美在线视频免费| 国产精品亚洲网站| 亚洲在线观看| 欧美日韩一区二区在线观看视频 | 中日韩高清电影网| 欧美人与性动交a欧美精品| 欧美国产先锋| 亚洲精品国产精品国自产在线| 久久综合伊人77777蜜臀| 久久一区二区三区av| 黄色另类av| 久久久久在线| 欧美第一黄色网| 激情综合五月天| 久久亚洲图片| 欧美激情在线有限公司| 亚洲精品视频在线观看网站| 欧美大胆a视频| 亚洲人成毛片在线播放| 日韩一区二区精品葵司在线| 欧美α欧美αv大片| 亚洲精品四区| 亚洲欧美99| 国际精品欧美精品| 美女精品视频一区| 亚洲欧洲在线视频| 亚洲性视频h| 国产深夜精品| 久久久五月天| 亚洲人体一区| 午夜宅男欧美| 在线免费观看欧美| 欧美伦理在线观看| 午夜精品久久久久久99热| 噜噜噜91成人网| 亚洲看片免费| 国产欧美另类| 欧美电影在线免费观看网站| 一区二区日韩欧美| 久久久国产成人精品| 亚洲激情女人| 国产精品女人毛片| 久久久久久**毛片大全| 亚洲精品久久久久久下一站| 欧美在线视频观看免费网站| 亚洲国产一区二区三区在线播| 欧美色精品天天在线观看视频 | 亚洲经典三级| 欧美自拍偷拍| 99精品视频免费| 国产一区二区成人久久免费影院| 免费日韩视频| 欧美一区二区三区精品| 亚洲国产精品久久久| 欧美一区二区三区日韩视频| 亚洲欧洲精品成人久久奇米网| 国产精品亚洲а∨天堂免在线| 免费观看亚洲视频大全| 亚洲欧美日本国产专区一区| 亚洲福利一区| 久久久综合网| 欧美一区二区三区四区夜夜大片| 亚洲国产欧美一区| 韩国精品在线观看| 国产精品网站在线播放| 欧美激情一区二区三区全黄| 久久99伊人| 亚洲在线中文字幕| 日韩午夜激情| 亚洲人妖在线| 亚洲福利国产精品| 欧美1区免费| 久久综合久色欧美综合狠狠| 午夜精品久久久久99热蜜桃导演| 日韩一区二区精品在线观看| 欧美jizzhd精品欧美喷水 | 亚洲另类视频| 亚洲国语精品自产拍在线观看| 久久精品一二三| 欧美在线视频导航| 欧美在线观看视频一区二区| 亚洲在线第一页| 亚洲一二三区精品| 中文一区二区在线观看| 99这里只有久久精品视频| 亚洲精品久久久久中文字幕欢迎你 | 久久久久久久成人| 久久九九免费视频| 久久高清福利视频| 久久精品欧美日韩| 久久精品国语| 欧美综合国产| 另类亚洲自拍| 欧美成人精品三级在线观看| 美女视频黄a大片欧美| 欧美大片在线观看一区| 米奇777超碰欧美日韩亚洲| 久热re这里精品视频在线6| 久久久噜噜噜久久中文字免| 久久久久国产精品麻豆ai换脸| 激情小说另类小说亚洲欧美| 一区二区精品在线| 亚洲天堂男人| 性感少妇一区| 久久婷婷激情| 欧美日韩国产一中文字不卡| 欧美日韩一区二区视频在线| 国产精品久久婷婷六月丁香| 国产欧美一区二区三区久久人妖| 国产午夜精品久久| 亚洲二区精品| 亚洲天堂网在线观看| 欧美在线视频观看免费网站| 久热精品视频在线免费观看 | 欧美在线日韩精品| 麻豆精品一区二区av白丝在线| 欧美激情亚洲另类| 宅男精品视频| 久久频这里精品99香蕉| 欧美日韩国产综合视频在线| 亚洲一区欧美激情| 极品日韩久久| 亚洲午夜一区二区| 麻豆精品国产91久久久久久| 亚洲人久久久| 欧美一区二区三区四区夜夜大片 | 国产精品日本一区二区| 国内精品久久久久久久果冻传媒 | 亚洲国产成人精品久久久国产成人一区 | 国产午夜精品一区二区三区欧美| 亚洲二区免费| 欧美一区二区三区免费观看| 亚洲第一二三四五区| 亚洲专区免费| 欧美精品一区二区三区在线播放 | 欧美va天堂| 国产夜色精品一区二区av| 亚洲乱码国产乱码精品精98午夜 | 老司机午夜精品| 亚洲一区二区av电影| 牛人盗摄一区二区三区视频| 国产精品一区二区你懂得| 亚洲欧洲精品成人久久奇米网 | 狂野欧美一区| 一区二区三区不卡视频在线观看| 久久手机精品视频| 国产综合在线看| 欧美一区二区三区在线视频|