摘 要:隨著科技的進(jìn)步,3D實(shí)時(shí)渲染越來(lái)越走近每一個(gè)人,而人們對(duì)于該項(xiàng)技術(shù)的運(yùn)用也隨之增加,除了電子游戲以外,3D實(shí)時(shí)渲染技術(shù)普遍應(yīng)用于醫(yī)療、工業(yè)、科研等領(lǐng)域。近年來(lái)興起的3D打印和虛擬現(xiàn)實(shí)更是把3D實(shí)時(shí)渲染作為基石而快速成長(zhǎng)。3D實(shí)時(shí)渲染技術(shù)一直以來(lái)存在幾個(gè)重大難題,快速處理大量法光源就是其中之一?,F(xiàn)實(shí)中,因?yàn)橛泄?,人們才能觀察到這個(gè)世界。在3D實(shí)時(shí)渲染中,雖然不一定需要有光,但是模擬出光的效果對(duì)于增加真實(shí)性至關(guān)重要,本文提出一種全新的渲染方法,在可接受的渲染開(kāi)銷范圍內(nèi),實(shí)現(xiàn)快速多光源渲染,并且不會(huì)對(duì)半透明和反走樣有任何限制。通過(guò)低分辨率軟光柵化為屏幕每一個(gè)區(qū)塊單獨(dú)計(jì)算光源列表,把光源限制在屏幕可見(jiàn)區(qū)域內(nèi),來(lái)剔除絕大多數(shù)不必要的計(jì)算。這種方法不會(huì)對(duì)傳統(tǒng)的向前光照有任何影響,僅僅在像素著色階段添加額外的光源列表,具有兼容性好、開(kāi)發(fā)便利、容易模塊化等優(yōu)點(diǎn)。
關(guān)鍵詞:OpenGL實(shí)時(shí)渲染;3D;
中圖分類號(hào):TN-9 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1674-3520(2014)-03-000267-01
一、為什么傳統(tǒng)向前光照不能處理多光源
在講述快速多光源渲染之前,首先需要說(shuō)明一下傳統(tǒng)的向前光照的基本流程。首先,3D物體通過(guò)頂點(diǎn)著色器,變換到投射空間,經(jīng)過(guò)GPU硬件光柵化之后,在像素著色器里,通過(guò)被插值過(guò)的3D物體的法線與光照相關(guān)信息,進(jìn)行光照計(jì)算[1]。以前可能在頂點(diǎn)著色器里計(jì)算光照比較多,不過(guò)無(wú)論如何,光照信息一般都是通過(guò)uniform變量傳給著色器,無(wú)論頂點(diǎn)還是像素,著色器每次獲取到的數(shù)據(jù)都是相同的,如果要進(jìn)行多光源處理,需要把所有光源信息都一起傳進(jìn)來(lái)。對(duì)于光源來(lái)說(shuō),不可能所有光源都會(huì)在投射空間占據(jù)所有像素點(diǎn),絕大多數(shù)光源可能僅僅占用不到5%,為了5%而在所有的像素內(nèi)計(jì)算光照顯然并不明智。由于GPU的特殊構(gòu)造,分歧計(jì)算開(kāi)銷很大,無(wú)論是在著色器內(nèi)判斷每個(gè)光源是否占用當(dāng)前像素,還是不判斷直接進(jìn)行光照計(jì)算,都是非常巨大的開(kāi)銷,也許十幾個(gè)光源的開(kāi)銷還能接受,但是幾百個(gè)光源顯然是不可能接受了。
二、快速多光源渲染的基本流程
第一步,通過(guò)與屏幕比例相同的超低分辨率軟光柵化,為每一個(gè)軟光柵化像素生成一個(gè)獨(dú)立的光源數(shù)據(jù)列表。第二步,把所有像素的光源數(shù)據(jù)列表合并為一個(gè)總列表,同時(shí)記錄下每個(gè)軟光柵化像素列表數(shù)據(jù)在總列表內(nèi)的開(kāi)始位置,以及當(dāng)前像素列表內(nèi)的光源數(shù)量。第三步,把每個(gè)像素在總列表內(nèi)的開(kāi)始位置與光源數(shù)量,按照像素在GPU內(nèi)的分布,組成一個(gè)雙通道紋理,一個(gè)通道是像素在總列表內(nèi)的開(kāi)始位置,另一個(gè)通道是光源數(shù)量。第四步,把第二步得到的總列表和第三步得到的紋理,傳給顯存。第五步,在渲染3D物體的像素著色器內(nèi),根據(jù)當(dāng)前像素在屏幕上的坐標(biāo),從第三步的紋理中,采樣出對(duì)應(yīng)的像素值,接下來(lái)就是,逐個(gè)獲取總列表中的光源數(shù)據(jù),然后計(jì)算光照結(jié)果。下圖為實(shí)際效果:
三、為什么要軟光柵化與軟光柵化步驟詳細(xì)
現(xiàn)代GPU最初的目的,就是為了把光柵化從CPU手中接過(guò)來(lái),以并行計(jì)算替代串行計(jì)算,從而實(shí)現(xiàn)至少3個(gè)數(shù)量級(jí)的提速[2] 。但是付出了代價(jià),GPU的并行計(jì)算導(dǎo)致每個(gè)象素之間沒(méi)有辦法進(jìn)行任何直接數(shù)據(jù)交流,每個(gè)象素的計(jì)算結(jié)果的大小必須是完全相同的。在快速多光源渲染的第一步,每個(gè)象素都是一個(gè)列表,而且每個(gè)象素的列表大小一般都是不同的,如果相同,某個(gè)象素列表里很可能會(huì)儲(chǔ)存超過(guò)200個(gè)光源數(shù)據(jù),所有的列表就都要超過(guò)200,否則就要丟失光源,這會(huì)導(dǎo)致總列表尺寸暴增,顯然不可行。因此光源列表,就必須由CPU進(jìn)行串行處理,也就是軟光柵化。雖然軟光柵化效率非常低,但是光源列表的分辨率并不需要與實(shí)際渲染窗口的分辨率相同,通常是四十分之一,例如1280X720分辨率的渲染窗口,光源列表分辨率可以只有32*18,總共576個(gè)象素。對(duì)于現(xiàn)代CPU來(lái)說(shuō),這樣低分辨率的軟光柵化當(dāng)然不會(huì)很慢??焖俣喙庠翠秩镜能浌鈻呕康牟皇抢L制圖形,而是生成光源列表,光源除了太陽(yáng)光之外,都可以抽象為點(diǎn)光源,也就是一個(gè)球體,因此并不需要實(shí)現(xiàn)完整的標(biāo)準(zhǔn)軟光柵化計(jì)算過(guò)程。光源列表不需要處理深度、半透明、顏色、模板,因此相關(guān)計(jì)算一律都可以省略,唯一需要的,就是把覆蓋到當(dāng)前像素的光源信息,添加到當(dāng)前像素的列表里。
四、快速多光源渲染的硬件需求、適用范圍和缺陷
快速多光源渲染最低需要顯卡支持Opengl2.0,并且支持動(dòng)態(tài)分支,相當(dāng)于DirectX9.0c,如果可能,建議在支持Opengl3.0也就是DirectX10的顯卡上實(shí)現(xiàn),Opengl3.0可以用Texture Buffer Objects,在著色器獲取光源數(shù)據(jù)的時(shí)候,可以大幅提高效率??焖俣喙庠翠秩咀钸m合小尺寸場(chǎng)景,而且比較分散的場(chǎng)合,比如室內(nèi)。如果一個(gè)場(chǎng)景內(nèi),上百個(gè)光源出現(xiàn)在攝像機(jī)附近,并且都覆蓋了整個(gè)攝像機(jī)范圍,這時(shí)候,相當(dāng)于每個(gè)列表中都存了相同的數(shù)據(jù),快速多光源渲染在這時(shí)候就無(wú)法起到任何作用了,這是最大的缺陷,因此,一定要避免此現(xiàn)象出現(xiàn),其實(shí)此時(shí)跟GPU像素填充率不足的情況非常近似,也可以用近似的方法來(lái)處理。
參考文獻(xiàn):
[1]OpenGL體系結(jié)構(gòu)審核委員會(huì)/Dave Shreiner/Mason Woo等 編著,OpenGL編程指南(第四版),人民郵電出版社,2005
[2]詹鵬;面向移動(dòng)設(shè)備的3D圖形光柵化處理單元的設(shè)計(jì)與實(shí)現(xiàn)[D];西安科技大學(xué);2012年
作者簡(jiǎn)介:張鴻浩,男,1984年生,本科,工程師助理,黑龍江省電子信息產(chǎn)品監(jiān)督檢察院。