2024年3月7日發(fā)(作者:自尊英語)

OpenGL 低級著色語言與高級著色語言
節(jié)選自偶的畢業(yè)論文,主要是對可編程圖形處理器, ARB_VERTEX_PROGRAM和glslang的簡單介紹。拋磚引玉,希望大家不吝賜教:)
Octane3d@
第二章 可編程圖形處理器
現(xiàn)代圖形流水線如圖-2.1所示。
(圖-2.1,圖形流水線)
應(yīng)用程序級(Application)實(shí)現(xiàn)物理模擬,處理用戶輸入,修改數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)庫訪問,幾何基元生成等功能。命令級(Command)提供命令緩沖區(qū),解釋執(zhí)行命令和管理圖形系統(tǒng)的狀態(tài)。幾何級(Geometry)對多項式表達(dá)的彎曲曲面求值,進(jìn)行幾何變換,光照計算,紋理坐標(biāo)生成,實(shí)現(xiàn)剪切,揀選與幾何基元組裝等功能。光柵化級(Rasterization)進(jìn)行三角形設(shè)置,對三角形進(jìn)行抽樣以生成片斷,并且對顏色和紋理坐標(biāo)進(jìn)行插值。紋理級(Texture)對紋理坐標(biāo)進(jìn)行變換,進(jìn)行紋理訪問與過濾。片斷級(Fragment)混合片斷顏色與紋理,進(jìn)行霧化操作,執(zhí)行深度、透明以及模版測試,最終生成要寫入幀緩沖區(qū)的象素。顯示級(Display)對象素顏色進(jìn)行嘎瑪校正后寫入幀緩沖區(qū)。命令與幾何級屬于對象空間的操作,其上的操作是每頂點(diǎn)的,主要是進(jìn)行幾何變換和光照計算,它的特點(diǎn)是大量(>= 1000萬個頂點(diǎn))復(fù)雜的浮點(diǎn)操作。紋理與片斷級輸入圖像空間的操作,其上的操作是每片斷的,主要是進(jìn)行紋理混合,它的特點(diǎn)是進(jìn)行海量(>= 10 億個片斷)但是較簡單的定點(diǎn)運(yùn)算。
圖形硬件的發(fā)展是一個逐漸對圖-2.1中的流水級增加硬件加速功能的過程。最早的圖形硬件只是一個簡單的幀緩沖區(qū),沒有任何硬件加速功能。之后逐漸添加硬件光柵化,硬件紋理映射,硬件幾何變換與光照計算,硬件反走樣等功能。按照圖形硬件所支持的硬件加速功能的多少與性質(zhì),可以把圖形硬件分為幾代。1984年,SGI公司發(fā)布了IRIS 1400圖形系統(tǒng),其中集成的圖形硬件可以實(shí)時光柵化平坦著色(flat-shaded)的多邊形,這是第一代圖形加速硬件。第二代圖形加速硬件以HP的SPX和SGI的GT為代表。它們提供Phong光照計算,Gouraud著色和Z-Buffer功能,光柵化性能也有了大大提高。1992年,SGI推出了RealityEngine [Akeley93],之后又于1996年推出了InfiniteReality [Montrym97],標(biāo)志著圖形加速硬件進(jìn)入第三代。RealityEngine在第二代圖形加速硬件的基礎(chǔ)上,增加了紋理映射與與全場景反走樣的功能,大大提高了實(shí)時渲染的真實(shí)感。上述的圖形加速硬件價格昂貴,只有高檔的圖形工作站才能夠配置,但是1996年3Dfx公司推出的面向PC平臺的Voodoo系列3D加速卡改變了這一局面。Voodoo卡介于第二與第三代圖形加速硬件之間,它提供Gouraud著色,硬件光柵化,硬件紋理映射,Z緩沖區(qū)等功能,將PC帶入了實(shí)時3D的時代。隨后,PC圖形硬件蓬勃發(fā)展,更高的三角形生成速率,更高的填充速率,多紋理功能,硬件幾何變換與光照計算,碰撞與環(huán)境映射以及全屏反走樣將其帶入了第三代圖形加速硬件的時代。此后,隨著PC游戲以及PC工作站的發(fā)展,可以說,PC圖形硬件的發(fā)展代表了圖形硬件技術(shù)發(fā)展的主流方向。
無論是傳統(tǒng)工作站圖形硬件,還是PC圖形硬件,從第一代到第三代,它們的一個共同特征就是都只實(shí)現(xiàn)了固定功能的渲染流水線,而不具備可編程能力。與這些圖形硬件相匹配,主要的3D API例如OpenGL 和 Direct3D作為一個狀態(tài)機(jī)實(shí)現(xiàn),用戶通過3D API提供的函數(shù)設(shè)置好相應(yīng)的狀態(tài),例如變換矩陣、材質(zhì)參數(shù)、光源參數(shù)、紋理混合模式等,然后傳入頂
點(diǎn)流。圖形硬件則利用內(nèi)置的固定渲染流水線和渲染算法對這些頂點(diǎn)進(jìn)行幾何變換、光照計算、光柵化、紋理混合、霧化操作、最終將處理結(jié)果寫入幀緩沖區(qū)。這種渲染體系限制用戶只能使用圖形硬件中固化的各種渲染算法。這雖然可以很好的滿足對渲染質(zhì)量要求不高的應(yīng)用,但難以滿足那些需要更高的靈活性和更真實(shí)的渲染質(zhì)量的實(shí)時圖形應(yīng)用。用戶已經(jīng)不再滿足于基于頂點(diǎn)的近似Phong模型光照計算(這是OpenGL和Direct3D采用的光照計算模型,這兩種API上的光照計算或者在支持硬件光照計算的的圖形硬件之上進(jìn)行,或者在CPU之上進(jìn)行。)和簡單的多紋理混合。用戶需要硬件加速的角色動畫支持,需要使用定制的光照模型(基于片斷的光照模型、各向異性光照模型、基于BRDF的光照模型),需要非真實(shí)渲染(卡通渲染、素描渲染),需要每片斷Fresnel效果,需要各種體積效果,需要過程紋理,以及各種以往只有在Renderman [Upstill89] 之上才能看到的3D效果。對于這些需求,傳統(tǒng)的圖形硬件是無能為力的。滿足這些需求的答案就是硬件可編程性。
2001年3月,nVidia公司推出了具有可編程能力的GeForce 3 [Lindholm01],從而將圖形加速硬件帶入了可編程的時代,即可編程圖形處理器,我們不妨將它們視為第四代圖形處理器?,F(xiàn)代圖形處理器的可編程引擎如圖-2.2所示。
(圖-2.2,現(xiàn)代圖形處理器的可編程引擎)
圖-2.2中的VE(頂點(diǎn)引擎或者頂點(diǎn)處理器)和PP(片斷引擎或者片斷處理器)就是可編程圖形處理器中的可編程部件。運(yùn)行于頂點(diǎn)處理器之上的程序稱為頂點(diǎn)著色程序(Vertex
Shader),它們的工作是進(jìn)行幾何變換和光照計算等操作。運(yùn)行于片斷處理器之上的程序稱為片斷著色程序(Fragment Shader),它們的工作是進(jìn)行紋理混合等操作。頂點(diǎn)著色程序的輸入是頂點(diǎn)流,輸出是處理后的頂點(diǎn)流。后者經(jīng)固定的光柵化模塊進(jìn)行三角形組裝和光柵化處理后用于生成片斷流送入片斷著色程序。片斷著色程序訪問紋理,進(jìn)行紋理混合并最終計算出片斷的顏色與深度信息送入后續(xù)流水級以進(jìn)行透明、深度、模板與霧化等操作。一個圖形處理器中一般包含多個頂點(diǎn)處理器和多個片斷處理器。如圖-2.2所示的圖形處理器包含2個頂點(diǎn)處理器,4個片斷處理器。同類型的處理器上運(yùn)行的總是同一個著色程序的一個拷貝,這些著色程序并行運(yùn)行,處理輸入流中的不同數(shù)據(jù)元素。輸入流中的數(shù)據(jù)元素類型相同,并且相互之間獨(dú)立。Shader在一個處理器上的每一次運(yùn)行只能處理輸入流中的一個元素。因此,頂點(diǎn)處理器或者片斷處理器可以看作是使用同一指令對不同數(shù)據(jù)元素進(jìn)行處理的單指令多
數(shù)據(jù)處理器(SIMD Processor)。
圖-2.3是頂點(diǎn)處理器的體系結(jié)構(gòu)。圖-2.4是片斷處理器的體系結(jié)構(gòu) [Michael02]。這兩種處理器都沒
(圖-2.3,頂點(diǎn)處理器體系結(jié)構(gòu))
(圖-2.4,片斷處理器體系結(jié)構(gòu))
有內(nèi)存的概念,所有的運(yùn)算都在寄存器之上進(jìn)行。它們的每一個寄存器都是四分量浮點(diǎn)寄存器,指令集中的指令可以同時對四個分量進(jìn)行運(yùn)算,因此可以把頂點(diǎn)處理器看作是一個基于寄存器的向量處理器。圖-2.3中的頂點(diǎn)數(shù)據(jù)寄存器用于只讀訪問當(dāng)前被處理的頂點(diǎn)的屬性,例如頂點(diǎn)位置、法向量、顏色和紋理坐標(biāo)。常量寄存器用于用于為頂點(diǎn)程序提供只讀常量參數(shù)或者程序參數(shù)。只寫的地址寄存器用于間接訪問常量寄存器。臨時寄存器用于保存中間運(yùn)算結(jié)果。只寫的輸出寄存器則用于輸出處理后的頂點(diǎn)屬性。圖-2.4中的顏色寄存器用于只讀訪問片斷的顏色。只讀的紋理坐標(biāo)寄存器用于訪問紋理坐標(biāo)和對紋理進(jìn)行抽樣。常量寄存器用于為片斷程序提供只讀常量參數(shù)或者程序參數(shù)。臨時寄存器用于保存中間運(yùn)算結(jié)構(gòu),臨時寄存器r0也是輸出寄存器。圖-2.3和圖-2.4是DirectX所定義的頂點(diǎn)/片斷處理器體系結(jié)構(gòu),但是它們也恰當(dāng)?shù)某橄罅死鏞penGL等其它類型的頂點(diǎn)/片斷處理器。
更詳細(xì)的寄存器與指令集說明將放在下一章進(jìn)行介紹。這里重點(diǎn)討論一下頂點(diǎn)/片斷處
理器區(qū)別于微處理器的一些特殊之處。微處理器的特點(diǎn)是標(biāo)量運(yùn)算、無內(nèi)在向量并行性、算術(shù)運(yùn)算單元少、有完善控制流指令、延遲低、帶寬小。而圖形應(yīng)用的特點(diǎn)確是大運(yùn)算量、大規(guī)模并行性、允許較長的延遲與深度前向流水。這就決定了圖形處理器和微處理器在體系結(jié)構(gòu)上存在著很大的差別。首先圖形處理器要盡可能的實(shí)現(xiàn)高度并行性。這種并行性分為兩種:數(shù)據(jù)并行性與流水線并行性。為了充分利用數(shù)據(jù)并行性,圖形處理器在兩個層次上進(jìn)行并行處理。第一層利用輸入數(shù)據(jù)流中數(shù)據(jù)元素之間的無關(guān)性,多個頂點(diǎn)(或片斷)處理器運(yùn)行一個頂點(diǎn)(或者片斷)著色程序的多個拷貝,同時作用于輸入數(shù)據(jù)流中的多個數(shù)據(jù)元素之上。從這個意義上說,圖形處理器是一個流處理器。第二層是利用圖形運(yùn)算包含大量向量運(yùn)算的特點(diǎn),實(shí)現(xiàn)指令級并行性。具體地說就是把多個同類型的標(biāo)量運(yùn)算合并到一個向量運(yùn)算之中。因此,圖形處理器又是一個向量處理器。其次流水并行性允許頂點(diǎn)著色程序與片斷著色程序同時運(yùn)行,前者的輸出恰為后者的輸入,構(gòu)成一種生產(chǎn)者消費(fèi)者的關(guān)系。再次為了保證大規(guī)模并行運(yùn)算,圖形處理器基本上不支持轉(zhuǎn)移指令或者只提供有限的支持,著色程序的靜態(tài)長度和動態(tài)可執(zhí)行長度也非常短。最后圖形處理器有著比微處理器多的多的算術(shù)邏輯運(yùn)算單元。圖形處理器的所有指令都具有相同的延遲,不存在各類流水競爭。
現(xiàn)在圖形處理器向著通用流處理器的方向發(fā)展,雖然它的重點(diǎn)應(yīng)用仍然是圖形應(yīng)用,通用性也遠(yuǎn)不是微處理器概念上的通用性??梢灶A(yù)測,未來的圖形處理器將支持功能更豐富的算術(shù)指令,提供更高程度的指令正交性和更強(qiáng)的轉(zhuǎn)移指令功能。而它的應(yīng)用范圍除了實(shí)時圖形應(yīng)用外,也會擴(kuò)展到全局光照計算、多體問題、分子動力學(xué)、彈性形變、流體模擬等科學(xué)計算領(lǐng)域 [Boltz03]。
第三章 低級著色語言
3.1 概述
要利用現(xiàn)代圖形處理器的可編程性,圖形程序員需要編寫在圖形處理器上運(yùn)行的程序,這種程序稱為著色程序(shader)。著色程序可以分為兩類,一類是頂點(diǎn)著色程序(vertex
shader),另一類是片斷著色程序(fragment shader)。頂點(diǎn)著色程序運(yùn)行于頂點(diǎn)處理器之上,每次激活處理一個頂點(diǎn);片斷著色程序運(yùn)行于片斷處理器之上,每次激活處理一個片斷。目前絕大多數(shù)著色程序都由低級著色語言寫成。圖形處理器通過通用的3D API(DirectX或者OpenGL)向圖形程序員提供可編程能力。
作為桌面PC上最主要的3D硬件接口,DirectX 從8.0開始就提供了對低級著色語言的支持,并在9.0中進(jìn)一步完善和發(fā)展。DirectX運(yùn)行庫分別定義了執(zhí)行vertex shader和fragment
shader的兩個虛擬機(jī),圖形程序員針對這兩個虛擬機(jī)編寫shader,GPU廠商則在顯卡驅(qū)動中實(shí)現(xiàn)這兩個虛擬機(jī)。隨著圖形處理器硬件能力和DirectX的飛速發(fā)展,shader虛擬機(jī)的規(guī)范也在不斷發(fā)展,目前DirectX 9.0支持多個版本的shader虛擬機(jī)。Vertex shader虛擬機(jī)有四個版本,分別是:vs_1_1、 vs_2_0、 vs_2_x和vs_3_0。Fragment shader(DirectX上稱為pixel
shader)虛擬機(jī)有六個版本,分別是:ps_1_1、ps_1_2、ps_1_4、ps_2_0、ps_2_x和ps_3_0。上述不同版本基本上可以分為三代。第一代是1.x版本,這一代的shader虛擬機(jī)對應(yīng)于早期的圖形處理器。這些圖形處理器提供的可編程資源(寄存器、指令集)都很有限,而且它們不提供轉(zhuǎn)移指令。第二代是2.x版本,這一代虛擬機(jī)對應(yīng)于目前的主流中檔圖形處理器。它們提供更多的寄存器和更大的指令集,而且提供基于常數(shù)的靜態(tài)轉(zhuǎn)移指令和有限的動態(tài)轉(zhuǎn)移指令。第三代是3.x版本,這一代虛擬機(jī)對應(yīng)于目前的主流高檔和未來的圖形處理器。它們提供更多的寄存器,包括靜態(tài)與動態(tài)轉(zhuǎn)移指令的更強(qiáng)大的指令集以及一個更一般的編程模型。
桌面PC的另一個主要3D硬件接口OpenGL接口也在不斷的加強(qiáng)對低級著色語言的支持。這種支持最初是硬件廠商通過添加私有的擴(kuò)展(openGL extension)[sgext]來實(shí)現(xiàn)的。例如nVidia公司通過添加NV_VERTEX_PROGRAM與NV_FRAGMENT_PROGRAM擴(kuò)展來提供對vertex shader和fragment shader的支持;ATI公司通過添加EXT_VERTEX_SHADER與ATI_FRAGMENT_SHADER來提供對vertex Shader和fragmentsShader的支持。這種做法的一個巨大缺點(diǎn)是不同廠商提供的編程接口不同,圖形程序員要想保證自己的應(yīng)用能夠在不同的圖形處理器上上都能順利運(yùn)行,必須針對每一個廠商的擴(kuò)展編寫不同的渲染代碼。為了解決這個問題,OpenGL體系管理委員會于2002年6月和2002年9月分別通過了兩個官方擴(kuò)展:ARB_VERTEX_PROGRAM與ARB_FRAGMENT_PROGRAM來統(tǒng)一對低級著色語言的支持。這兩個擴(kuò)展同樣定義了運(yùn)行vertex shader與fragment shader的兩個shader虛擬機(jī),圖形程序員和顯卡廠商分別針對這兩個虛擬機(jī)編寫應(yīng)用程序和驅(qū)動程序。目前這兩個擴(kuò)展的版本是1.0(arbvp10和arbfp10),相當(dāng)于DirectX中的vs_1_x和ps_1_x。這兩個擴(kuò)展的2.0的版本(arbvp20和arbfp20,相當(dāng)于DirectX中的vs_2_x和ps_2_x)現(xiàn)在也在制定之中。
本文的研究對象是OpenGL 2.0中提出的高級著色語言glslang及其優(yōu)化編譯技術(shù)。為此,本章的后續(xù)幾節(jié)將重點(diǎn)介紹做為glslang編譯器目標(biāo)機(jī)器的arbvp10虛擬機(jī) [arbvp10] 與
arbfp10虛擬機(jī) [arbfp10] 和arbvp20虛擬機(jī)與arbfp20虛擬機(jī)。但由于目前arbvp20/arbfp20的規(guī)范還未公布,我們只能在現(xiàn)有虛擬機(jī)的基礎(chǔ)上設(shè)想這兩種虛擬機(jī)的硬件能力。
3.2 arbvp10 著色語言
3.2.1 概述
Vertex shader在OpenGL渲染流水線中的位置和作用如圖-3.1所示。
(圖-3.1,OpenGL中的頂點(diǎn)著色程序)
用戶編寫的LLSL vertex shader(在OpenGL中稱為vertex program)可以在用戶的控制下取代OpenGL的固定幾何變換與光照處理模塊。當(dāng)用戶允許vertex program模式時,vertex
program在每指定一個頂點(diǎn)坐標(biāo)或者頂點(diǎn)屬性0時執(zhí)行。Vertex program 每次處理一個頂點(diǎn),對不同頂點(diǎn)的處理互不影響。它的輸入是頂點(diǎn)的屬性,包括坐標(biāo)、法向量、顏色、紋理坐標(biāo)等;輸出是處理后的頂點(diǎn)屬性,包括齊次剪切空間頂點(diǎn)坐標(biāo)、顏色、紋理坐標(biāo)等。Vertex
program一般來說需要完成頂點(diǎn)世界-觀察坐標(biāo)變換與投影坐標(biāo)變換、基于頂點(diǎn)的光照計算和紋理坐標(biāo)生成等任務(wù)。
3.2.2 arbvp10虛擬機(jī)
arbvp10虛擬機(jī)的框圖如圖-3.2所示。
(圖-3.2,arbvp10虛擬機(jī))
粗略的說,arbvp10虛擬機(jī)可以看作是一個基于寄存器的向量處理器。arbvp10虛擬機(jī)中沒有內(nèi)存的概念,所有的數(shù)據(jù)都保存在寄存器中。除地址寄存器外,所有的寄存器都是四分量浮點(diǎn)寄存器,也就是說,每一個寄存器可以保存四個浮點(diǎn)數(shù)。arbvp10虛擬機(jī)包含五種寄存器:頂點(diǎn)屬性寄存器、頂點(diǎn)結(jié)果寄存器、臨時寄存器、地址寄存器與程序參數(shù)寄存器。
arbvp10虛擬機(jī)支持至少16個頂點(diǎn)屬性寄存器。這些寄存器可以通過表-3.1中的寄存的器名直接訪問。
頂點(diǎn)屬性傳統(tǒng)寄存
器名
on
[n]
y
ary
rd
rd
rd [n]
index
index [n]
分量
(x, y, z, w)
(w, w, w, w)
(w, w, w, w)
(x, y, z, 1)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(f, 0, 0, 1)
(s, t, r, q)
(s, t, r, q)
(i, i, i, i)
頂點(diǎn)屬性一般
寄存器名
[0]
[1]
[1]
[2]
[3]
[3]
[4]
[5]
[8]
[8 + n]
N/A
說明
對象坐標(biāo)
頂點(diǎn)權(quán)重 0 – 3
頂點(diǎn)權(quán)重 n – n + 3
頂點(diǎn)法向量
主顏色
主顏色
次顏色
霧化坐標(biāo)
紋理坐標(biāo),紋理單元0
紋理坐標(biāo),紋理單元n
頂點(diǎn)矩陣索引 0 – 3
(i, i, i, i) 頂點(diǎn)矩陣索引 n – n + 3
N/A
(表-3.1,頂點(diǎn)屬性寄存器名)
表-3.1中的頂點(diǎn)屬性寄存器有兩種命名方式。一種是第一列中的頂點(diǎn)屬性傳統(tǒng)寄存器名,另一種是頂點(diǎn)屬性一般寄存器名。前者對應(yīng)于通過glVertex,glNormal等函數(shù)調(diào)用設(shè)置的頂點(diǎn)屬性;后者對應(yīng)于通過glVertexAttrib函數(shù)調(diào)用設(shè)置的頂點(diǎn)屬性。兩種設(shè)置頂點(diǎn)屬性的方式都是可行的,但是不能混合使用。頂點(diǎn)屬性寄存器也可以通過申明綁定到某一個頂點(diǎn)屬性寄存器名的屬性變量訪問,例如:
ATTRIB pos = on; # pos等價于 on。
頂點(diǎn)屬性寄存器是vertex program的輸入,是只讀寄存器。
arbvp10虛擬機(jī)支持至少8個頂點(diǎn)結(jié)果寄存器。這些寄存器可以通過表-3.2中的寄存器名直接訪問。
頂點(diǎn)結(jié)果寄存器名
on
y
ary
y
分量 描述
(x, y, z, w) 剪切空間坐標(biāo)
(r, g, b, a) 正面主顏色
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
正面主顏色
正面次顏色
正面主顏色
正面主顏色
正面次顏色
背面主顏色
背面主顏色
背面次顏色
霧化坐標(biāo)
點(diǎn)大小
紋理坐標(biāo)
紋理坐標(biāo)
ary
(r, g, b, a)
(r, g, b, a)
y
(r, g, b, a)
..condary
(r, g, b, a)
(f, *, *, *)
rd
ize
rd
rd [n]
(s, *, *, *)
(s, t, r, q)
(s, t, r, q)
(表-3.2,頂點(diǎn)結(jié)果寄存器)
也可以通過申明綁定到某一個頂點(diǎn)結(jié)果寄存器名的輸出變量訪問,例如:
OUTPUT clipPos = on; # clipPos等價于on
頂點(diǎn)結(jié)果寄存器是vertex program的輸出,是只寫寄存器。
arbvp10虛擬機(jī)支持至少12個臨時寄存器。臨時寄存器的值在vertex program激活時無定義,也不能在vertex program的兩次運(yùn)行間共享。它們一般用于保存vertex program執(zhí)行過程中的臨時運(yùn)算結(jié)果。臨時寄存器通過申明臨時變量使用:
TEMP temp0, temp1, temp2; # 申明了三個綁定到三個臨時寄存器的臨時變量。
arbvp10虛擬機(jī)支持至少一個地址寄存器。地址寄存器是四分量整數(shù)寄存器,并且只有x分量能夠訪問。地址寄存器用作訪問程序參數(shù)數(shù)組的下標(biāo)變量。地址寄存器通過申明地址變量使用:
ADDRESS Areg; # 定義了一個綁定到地址寄存器的地址變量。
程序參數(shù)寄存器。arbvp10虛擬機(jī)支持至少96個程序參數(shù)寄存器。程序參數(shù)寄存用于為vertex program提供執(zhí)行所需要的只讀參數(shù)。程序參數(shù)寄存器通過申明PARAM變量使用。需要指出的是PARAM類型的變量必須在申明的時候進(jìn)行初始化,這一個初始化過程稱為程序參數(shù)寄存器的顯式綁定,即將這一PARAM變量綁定到某一個常量。程序參數(shù)寄存器可以綁定到四種量(可綁定量):即常量、程序局部參數(shù)、程序環(huán)境參數(shù)和OpenGL狀態(tài)變量。下面具體討論每一種可綁定量及其綁定規(guī)則。注意除了顯式綁定外還有隱式綁定。即對于shader中直接使用的一個可綁定量,系統(tǒng)會自動申明一個匿名PARAM變量綁定到該可綁定量。
1)常量綁定。PARAM變量通過如下方式綁定到常量:
PARAM par1 = 1.0; # par1 的值成為 {1.0,1.0,1.0,1.0}
PARAM par2 = {1.0,2.0,3.0,4.0}; # par2的值成為 {1.0,2.0,3.0,4.0}
2)程序局部參數(shù)。常量的值只能在vertex program內(nèi)部設(shè)置。如果要從vertex program外部提供常量值,則需要通過程序局部參數(shù)實(shí)現(xiàn)。OpenGL應(yīng)用通過glProgramLocalParameter
可以為某一個特定的vertex program設(shè)置最多達(dá)96個程序局部參數(shù),這些參數(shù)只對該vertex
program有效。vertex program通過申明綁定到一個或多個程序局部參數(shù)的PARAM變量來訪問該參數(shù)。
PARAM par = [8];
PARAM b [2] = [4..5];
3)程序環(huán)境參數(shù)。程序環(huán)境參數(shù)與程序局部參數(shù)類似,但程序環(huán)境參數(shù)通過glProgramEnvParameter設(shè)置并且對所有的vertex program有效。Vertex program通過申明綁定到一個或多個程序環(huán)境參數(shù)的PARAM變量來訪問該參數(shù)。
PARAM a = [8];
PARAM b [2] = [4..5];
4)OpenGL 狀態(tài)變量。用戶可以通過申明綁定到表-3.3中的狀態(tài)變量訪問OpenGL狀態(tài)變量。
狀態(tài)變量名
材質(zhì)狀態(tài)變量:
t
e
ar
ess
.*
.*
光源狀態(tài)變量:
[n].ambient
[n].diffu
[n].specular
[n].position
[n].attenuation
分量
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(x, y, z, w)
(a, b, c, e)
描述
正面材質(zhì)環(huán)境反射系數(shù)
正面材質(zhì)漫反射系數(shù)
正面材質(zhì)鏡面反射系數(shù)
正面材質(zhì)鏡面高光系數(shù)
正面材質(zhì)的相關(guān)系數(shù)(* 同上)
反面材質(zhì)的相關(guān)系數(shù)(* 同上)
光源 n 的環(huán)境光強(qiáng)
光源 n 的滿反射光強(qiáng)
光源 n 的鏡面反射光強(qiáng)
光源 n 的位置
光源 n 的衰減系數(shù)和聚光燈指數(shù)
[n].ion
(x, y, z, c) 光源 n 的聚光燈方向和衰減角余弦
(x, y, z, 1) 光源 n 的無限半角
[n].half
(r, g, b, a) 光照模型的環(huán)境光強(qiáng)
t
光照模型的正面場景光強(qiáng)
olor
(r, g, b, a)
(r, g, b, a) 光照模型的正面場景光強(qiáng)
.*
.*
rod [n].ambient
rod [n].diffu
rod [n].specular
rod [n].front.*
rod [n].back.*
紋理坐標(biāo)生成狀態(tài)變量:
[n].eye.s
[n].eye.t
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
光照模型的反面場景光強(qiáng)
(a, b, c, d) 紋理單元 n 的TexGen觀察空間
平面系數(shù) s 坐標(biāo)
(a, b, c, d) 紋理單元 n 的TexGen觀察空間
[n].eye.r
[n].eye.q
[n].object.*
霧化狀態(tài)變量:
剪切平面狀態(tài)變量:
[n].plane
點(diǎn)狀態(tài)變量:
ation
矩陣狀態(tài)變量:
iew [n]
tion
e [n]
e [n]
(a, b, c, d)
(a, b, c, d)
(a, b, c, d)
(r, g, b, a)
(d, s, e, r)
(a, b, c, d)
(s, n, x, f)
(a, b, c, 1)
平面系數(shù) t 坐標(biāo)
紋理單元 n 的TexGen觀察空間
平面系數(shù) r 坐標(biāo)
紋理單元 n 的TexGen觀察空間
平面系數(shù) q 坐標(biāo)
紋理單元 n 的 TexGen 對象空間
平面系數(shù) s/t/r/q 坐標(biāo)
霧顏色
霧化系數(shù)
剪切平面 n 的平面方程系數(shù)
點(diǎn)大小
點(diǎn)大小衰減常數(shù)
模型觀察矩陣 n
投影矩陣
模型觀察-投影矩陣
紋理矩陣 n
模型觀察矩陣調(diào)色板 n
頂點(diǎn)程序矩陣 n
m [n]
(表-3.3,可綁定的OpenGL狀態(tài)變量)
例如,可以通過如下方式申明綁定到當(dāng)前材質(zhì)的環(huán)境反射系數(shù)狀態(tài)變量的PARAM變量:
PARAM ambient = t;
隱式或者顯式申明的與四種寄存器對應(yīng)的變量的個數(shù)不能超過相應(yīng)的資源限制。具體的數(shù)值可以通過OpenGL的查詢函數(shù)獲得。但是OpenGL實(shí)現(xiàn)必須支持上面提到的那些最小值。
3.2.3 arbvp10指令集
arbvp10虛擬機(jī)線性執(zhí)行當(dāng)前vertex program。一個vertex program最多允許包含128條指令(或更多,由具體的OpenGL實(shí)現(xiàn)確定)。arbvp10虛擬機(jī)支持27條SIMD指令。這些指令的操作數(shù)可以是標(biāo)量,也可以是四分量向量。指令執(zhí)行的結(jié)果可以是一般向量,也可以是由標(biāo)量重復(fù)擴(kuò)展而成的向量。當(dāng)操作數(shù)是向量時,對向量四個分量的運(yùn)算同時進(jìn)行。arbvp10指令的一般格式是:
Opcode dst, [-]s0 [,[-]s1[,[-]s2]]; # 注釋,[ ] 表示可選。
例如:
MOV R2, R2;
MAD R1, R2, R3, -R4;
表-3.4列出了27條指令的格式和簡單說明,其中 v 表示向量,s表示標(biāo)量,ssss表示由標(biāo)
量重復(fù)擴(kuò)展而成的向量,a表示單一的地址寄存器分量:
指令
ABS
ADD
ARL
DP3
DP4
DPH
DST
EX2
EXP
FLR
FRC
LG2
LIT
LOG
MAD
MAX
MIN
MOV
MUL
POW
RCP
RSQ
SGE
SLT
SUB
SWZ
XPD
目的操作數(shù) 源操作數(shù)
v
v
a
ssss
ssss
ssss
v
ssss
v
v
v
ssss
v
v
v
v
v
v
v
ssss
ssss
ssss
v
v
v
v
v
v
v, v
v
v, v
v, v
v, v
v, v
s
s
v
v
s
v
s
v, v, v
v, v
v, v
v
v, v
s, s
s
s
v, v
v, v
v, v
v
v, v
說明
求絕對值
相加(按分量)
載入到地址寄存器 *
三分量點(diǎn)積
四分量點(diǎn)積
其次點(diǎn)積
計算距離向量
計算底數(shù)為2的指數(shù)
計算底數(shù)為2的指數(shù)(近似)*
計算比 v 小的最大整數(shù)(按分量)
計算 v 的小數(shù)部分(按分量)
計算底數(shù)為2的對數(shù)
計算光照計算系數(shù)
計算底數(shù)為2的對數(shù)(近似)*
先乘后加
計算最大值(按分量)
計算最小值(按分量)
賦值
相乘(按分量)
計算指數(shù)
計算倒數(shù)
計算平方根的倒數(shù)
大于等于時置位(按分量)
小于時置位(按分量)
相減(按分量)
擴(kuò)展的分量下標(biāo)置換
計算叉積
(表-3.4,帶 * 的指令只能用于 Vertex Program)
源操作可以取負(fù)。例如,假設(shè) R1 = {1, 2, 3, 4},那么執(zhí)行下面的指令后,R0的值為:
MOV R0, -R1; # R0 = {-1, -2, -3, -4}。
作為源操作數(shù)的的向量操作數(shù)可以進(jìn)行分量下標(biāo)置換操作。例如,假設(shè) R1 = {1, 2, 3, 4},那么執(zhí)行下列指令后,R0的值分別為:
MOV R0, R1; # R0 = {1, 2, 3, 4}。
MOV R0, R1.y; # R0 = {2, 2, 2, 2}。
MOV R0, ; # R0 = {2, 3, 4, 1}。
作為目的操作數(shù)的向量操作數(shù)可以設(shè)置可寫掩碼。例如,假設(shè)R0 = {0, 0, 0, 0},R1 = {1, 2, 3,
4},那么執(zhí)行下面的指令后,R0的值為:
MOV , R1; # R0 = {1, 2, 0, 0}。
3.2.4 一個簡單的arbvp10程序
?。RBvp1.0
ATTRIB pos = on;
PARAM mat [4] = {};
# Transform by concatenation of the MODELVIEW and PROJECTION matrices.
DP4 on.x, mat [0], pos;
DP4 on.y, mat [0], pos;
DP4 on.z, mat [0], pos;
DP4 on.w, mat [0], pos;
# Pass the primary color through w/o lighting.
MOV . ;
END
(圖-3.3,arbvp10著色程序)
上面的程序簡單的將頂點(diǎn)的坐標(biāo)由對象空間變換到齊次剪切空間,然后將頂點(diǎn)顏色不加修改的輸出。
3.3 arbfp10著色語言
3.3.1 概述
Fragment shader在OpenGL渲染流水線中的位置和作用如圖-3.4所示。
(圖-3.4,OpenGL中的片段著色程序)
用戶編寫的LLSL fragment shader(在OpenGL中稱為fragment program)可以在用戶的控制下取代OpenGL的固定片斷處理模塊。當(dāng)用戶允許fragment program模式時,fragment
program 在光柵化模塊每生成一個片斷時執(zhí)行。Fragment program 每次處理一個片斷,對不同片斷的處理互不影響。它的輸入是片斷的屬性,包括片斷顏色、紋理坐標(biāo)、霧化坐標(biāo)等;
輸出是片斷顏色和深度緩沖區(qū)深度值。Fragment program一般來說需要完成紋理混合等任務(wù)。
3.3.2 arbfp10虛擬機(jī)
arbfp10虛擬機(jī)的框圖如圖-3.5所示。
(圖-3.5,arbfp10虛擬機(jī))
與arbvp10虛擬機(jī)類似,arbfp10虛擬機(jī)也可以看作是一個基于寄存器的向量處理器。arbfp10虛擬機(jī)中同樣沒有內(nèi)存的概念,所有的數(shù)據(jù)都保存在寄存器中。所有的寄存器都是四分量浮點(diǎn)寄存器。arbfp10虛擬機(jī)包括四種寄存器:片斷屬性寄存器、片斷結(jié)果寄存器、臨時寄存器與程序參數(shù)寄存器。
arbfp10虛擬機(jī)至少支持10個片斷屬性寄存器。這些寄存器可以通過表-3.5中的寄存器名直接訪問。
片斷屬性寄存器名
y
ary
rd
rd [n]
rd
分量
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(s, t, r, q)
(s, t, r, q)
(f, 0, 0, 1)
說明
片斷主顏色
片斷主顏色
片斷從顏色
紋理坐標(biāo),對應(yīng)紋理單元 0
紋理坐標(biāo),對應(yīng)紋理單元 n
片斷霧化坐標(biāo)
(x, y, z, 1/w) 片斷在窗口中的位置
on
(表-3.5,片斷屬性寄存器名)
片斷屬性寄存器也可以通過申明綁定到某一個片斷屬性寄存器的屬性變量訪問,例如:
ATTRIB clr = ; # clr 等價于。
片斷屬性寄存器是fragment program的輸入,是只讀寄存器。
arbfp10虛擬機(jī)至少支持10個片斷結(jié)果寄存器。這些寄存器可以表-3.6中的寄存器名直接訪問。
片斷結(jié)果寄存器名
分量 描述
(r, g, b, a) 片斷輸出顏色
(*, *, d, *) 片斷深度
(表-3.6,片斷結(jié)果寄存器)
也可以通過申明綁定到某一個片斷結(jié)果寄存器的輸出變量訪問,例如:
OUTPUT finalClr = ; # finalClr等價于。
片斷結(jié)果寄存器是fragment program的輸出,是只寫寄存器。
arbfp10虛擬機(jī)至少支持16個臨時寄存器。臨時寄存器的值在fragment program激活時無定義,也不能在fragment program的兩次運(yùn)行間共享。它們一般用于保存fragment program運(yùn)行過程中的臨時運(yùn)算結(jié)果。臨時寄存器通過申明臨時變量使用:
TEMP temp0, temp1, temp2; # 申明了三個綁定到三個臨時寄存器的臨時變量。
arbfp10虛擬機(jī)至少支持24個程序參數(shù)寄存器。程序參數(shù)寄存用于為fragment program提供執(zhí)行所需要的只讀參數(shù)。程序參數(shù)寄存器通過申明PARAM變量使用。需要指出的是PARAM類型的變量必須在申明的時候進(jìn)行初始化,這一個初始化過程稱為程序參數(shù)寄存器的顯式綁定,即將這一PARAM變量綁定到某一個常量。程序參數(shù)寄存器可以綁定到四種量(可綁定量):即常量、程序局部參數(shù)、程序環(huán)境參數(shù)和OpenGL狀態(tài)變量。下面具體討論每一種可綁定量及其綁定規(guī)則。注意除了顯式綁定外還有隱式綁定。即對于shader中直接使用的一個可綁定量,系統(tǒng)會自動申明一個匿名PARAM變量綁定到該可綁定量。
1)常量綁定。PARAM變量通過如下方式綁定到常量:
PARAM par1 = 1.0; # par1 的值成為 {1.0,1.0,1.0,1.0}
PARAM par2 = {1.0,2.0,3.0,4.0}; # par2的值成為 {1.0,2.0,3.0,4.0}
2)程序局部參數(shù)。常量的值只能在fragment program內(nèi)部設(shè)置。如果要從fragment
program外部提供常量值,則需要通過程序局部參數(shù)實(shí)現(xiàn)。OpenGL應(yīng)用通過glProgramLocalParameter可以為某一個特定的fragment program設(shè)置最多達(dá)24個程序局部參數(shù),這些參數(shù)只對該fragment program有效。Fragment program通過申明綁定到一個或多個程序局部參數(shù)的PARAM變量來訪問該參數(shù)。
PARAM par = [8];
PARAM b [2] = [4..5];
3)程序環(huán)境參數(shù)。程序環(huán)境參數(shù)與程序局部參數(shù)類似,但程序環(huán)境參數(shù)通過glProgramEnvParameter設(shè)置并且對所有的fragment program有效。Fragment program通過申明綁定到一個或多個程序環(huán)境參數(shù)的PARAM變量來訪問該參數(shù)。
PARAM a = [8];
PARAM b [2] = [4..5];
4)OpenGL狀態(tài)變量。用戶可以通過申明綁定到表-3.7中的狀態(tài)變量訪問OpenGL狀態(tài)變量。
狀態(tài)變量名
材質(zhì)狀態(tài)變量:
t
e
ar
ess
.*
.*
光源狀態(tài)變量:
[n].ambient
分量
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
描述
正面材質(zhì)環(huán)境反射系數(shù)
正面材質(zhì)漫反射系數(shù)
正面材質(zhì)鏡面反射系數(shù)
正面材質(zhì)鏡面高光系數(shù)
正面材質(zhì)的相關(guān)系數(shù)(* 同上)
反面材質(zhì)的相關(guān)系數(shù)(* 同上)
光源 n 的環(huán)境光強(qiáng)
[n].diffu
[n].specular
[n].position
[n].attenuation
(r, g, b, a)
(r, g, b, a)
(x, y, z, w)
(a, b, c, e)
光源 n 的滿反射光強(qiáng)
光源 n 的鏡面反射光強(qiáng)
光源 n 的位置
光源 n 的衰減系數(shù)和聚光燈指數(shù)
[n].ion
(x, y, z, c) 光源 n 的聚光燈方向和衰減角余弦
(x, y, z, 1) 光源 n 的無限半角
[n].half
(r, g, b, a) 光照模型的環(huán)境光強(qiáng)
t
光照模型的正面場景光強(qiáng)
olor
(r, g, b, a)
.*
.*
rod [n].ambient
rod [n].diffu
rod [n].specular
rod [n].front.*
rod [n].back.*
霧化狀態(tài)變量:
深度狀態(tài)變量:
矩陣狀態(tài)變量:
iew [n]
tion
e [n]
e [n]
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(r, g, b, a)
(d, s, e, r)
(n, f, d, l)
光照模型的正面場景光強(qiáng)
光照模型的反面場景光強(qiáng)
霧顏色
霧化系數(shù)
深度范圍
模型觀察矩陣 n
投影矩陣
模型觀察-投影矩陣
紋理矩陣 n
模型觀察矩陣調(diào)色板 n
頂點(diǎn)程序矩陣 n
m [n]
(表-3.7,可綁定的OpenGL狀態(tài)變量)
例如,可以通過如下方式申明綁定到當(dāng)前材質(zhì)的環(huán)境反射系數(shù)狀態(tài)變量的PARAM變量:
PARAM ambient = t;
隱式或者顯式申明的與四種寄存器對應(yīng)的變量的個數(shù)不能超過相應(yīng)的資源限制。具體的數(shù)值可以通過OpenGL的查詢函數(shù)獲得。但是OpenGL實(shí)現(xiàn)必須支持上面提到的那些最小值。
3.3.3 arbfp10指令集
arbfp10虛擬機(jī)線性執(zhí)行當(dāng)前fragment program。一個fragment program最多允許包含72條指令(或更多,由具體的的OpenGL實(shí)現(xiàn)確定)。其中算術(shù)指令不能超過48條,紋理指令不能超過24條。arbfp10虛擬機(jī)支持33條指令。其中29條是SIMD算是指令,4條是紋理指令。這些指令的操作數(shù)可以是標(biāo)量,也可以是四分量向量。指令執(zhí)行的結(jié)果可以是一般向量,也可以是由標(biāo)量重復(fù)擴(kuò)展而成的向量。當(dāng)操作數(shù)是向量時,對向量四個分量的運(yùn)算同時
進(jìn)行。arbfp10指令的一般格式是:
Opcode dst, [-]s0 [,[-]s1[,[-]s2]]; # 注釋,[ ] 表示可選。
例如:
MOV R2, R2;
MAD R1, R2, R3, -R4;
表-3.8列出了33條指令的格式和簡單說明,其中 v 表示向量,s表示標(biāo)量,ssss表示由標(biāo)量重復(fù)擴(kuò)展而成的向量,a表示單一的地址寄存器分量:
指令 目的操作數(shù) 源操作數(shù)
ABS
ADD
CMP
COS
DP3
DP4
DPH
DST
EX2
FLR
FRC
LG2
LIT
LRP
MAD
MAX
MIN
MOV
MUL
POW
RCP
RSQ
SCS
SGE
SIN
SLT
SUB
SWZ
XPD
KIL
TEX
TXB
TXP
v
v
v
ssss
ssss
ssss
ssss
v
ssss
v
v
ssss
v
v
v
v
v
v
v
ssss
ssss
ssss
ss--
v
ssss
v
v
v
v
v
v
v
v
v, v
v, v, v
s
v, v
v, v
v, v
v, v
s
v
v
s
v
v, v, v
v, v, v
v, v
v, v
v
v, v
s, s
s
s
s
v, v
s
v, v
v, v
v
v, v
v
v, u, t
v, u, t
說明
求絕對值
相加(按分量)
條件賦值(按分量)*
計算余弦 *
三分量點(diǎn)積
四分量點(diǎn)積
齊次點(diǎn)積
計算距離向量
計算底數(shù)為2的指數(shù)
計算比v小的最大整數(shù)(按分量)
計算v的小數(shù)部分(按分量)
計算底數(shù)為2的對數(shù)
計算光照計算系數(shù)
線性插值 *
先乘后加
計算最大值(按分量)
計算最小值(按分量)
賦值
相乘(按分量)
計算指數(shù)
計算倒數(shù)
計算平方根的倒數(shù)
同時計算正弦與余弦 *
大于等于時置位(按分量)
計算正弦 *
小于時置位(按分量)
相減(按分量)
擴(kuò)展的分量下標(biāo)置換
計算叉積
終止Fragment Program運(yùn)行 *
紋理抽樣 *
帶偏移的紋理抽樣 *
紋理坐標(biāo)投影后抽樣 *
v v, u, t
(表-3.8,帶 * 的指令只能用于 Fragment Program)
源操作數(shù)可以取反。例如,假設(shè) R1 = {1, 2, 3, 4},那么執(zhí)行下面的指令后,R0的值為:
MOV R0, -R1; # R0 = {-1, -2, -3, -4}。
作為源操作數(shù)的的向量操作數(shù)可以進(jìn)行分量下標(biāo)置換操作。例如,假設(shè) R1 = {1, 2, 3, 4},那么執(zhí)行下列指令后,R0的值分別為:
MOV R0, R1; # R0 = {1, 2, 3, 4}。
MOV R0, R1.y; # R0 = {2, 2, 2, 2}。
MOV R0, ; # R0 = {2, 3, 4, 1}。
作為目的操作數(shù)的向量操作數(shù)可以設(shè)置可寫掩碼。例如,假設(shè)R0 = {0, 0, 0, 0},R1 = {1, 2, 3,
4},那么執(zhí)行下面的指令后,R0的值為:
MOV , R1; # R0 = {1, 2, 0, 0}。
3.3.4 一個簡單的arbfp10程序
??!ARBfp1.0
TEMP temp; # temporary.
ATTRIB tex0 = rd [0];
OUTPUT out = ;
TEX temp, tex0, texture [0], 2D; # Fetch texture.
MOV out, temp; # Output result fragment color.
END
(圖-3.6,arbfp10著色程序)
上面的程序根據(jù)紋理坐標(biāo)訪問紋理,然后將紋理抽樣值作為片斷的顏色輸出。
3.4 arbvp20與arbfp20 著色語言
arbvp10/arbfp10虛擬機(jī)的一個重要的特點(diǎn)是它們不支持任何類型的轉(zhuǎn)移指令,包括絕對轉(zhuǎn)移指令、條件轉(zhuǎn)移指令和過程調(diào)用與返回指令。這一特點(diǎn)準(zhǔn)確的反映了arbvp10/arbfp10虛擬機(jī)所面向的早期圖形處理器較弱的的硬件處理能力。對于簡單的著色程序來說,線性執(zhí)行的編程模型可以滿足大多數(shù)需求。但是復(fù)雜的圖形應(yīng)用,特別是要達(dá)到電影集并渲染效果的實(shí)時圖形應(yīng)用需要編寫復(fù)雜的著色程序。另一方面,圖形處理器正在逐漸向著一般的流處理器發(fā)展,圖形處理器可以支持的指令集也越來越接近微處理器指令集。為此,需要定義與之匹配的具有更強(qiáng)能力的虛擬機(jī)。與arbvp10/arbfp10的發(fā)展類似,各個硬件廠商提出了自己的OpenGL擴(kuò)展(例如nVidia的NV_VERTEX_PROGRAM2 [nvvp20])來定義這一虛擬機(jī)。為了解決圖形程序員需要支持不同擴(kuò)展的問題,OpenGL ARB目前正在著手制定arbvp20/arbfp20擴(kuò)展來統(tǒng)一不同的擴(kuò)展。由于arbvp20/arbfp20標(biāo)準(zhǔn)還未公布,我們只能結(jié)合NV_VERTEX_PROGRAM2擴(kuò)展和arbvp10/arbfp10標(biāo)準(zhǔn)來預(yù)測可能的arbvp20/arbfp20標(biāo)準(zhǔn)。
NV_VERTEX_PROGRAM2(下面簡單表示為nvvp20)是nVidia公司提出的面向nVidia最新圖形處理器芯片NV3X的OpenGL擴(kuò)展。考慮到nVidia公司在arbvp10制訂過程中所起的作用,可以相信arbvp20將具有很多nvvp20的特性。Nvvp20對于arbvp10最重要的擴(kuò)展是增加了無條件轉(zhuǎn)移、條件轉(zhuǎn)移和過程調(diào)用與返回指令。這樣,用nvvp20編寫的著色程序就可以具有非常復(fù)雜的結(jié)構(gòu)和功能。
為了支持轉(zhuǎn)移指令,nvvp20增加了一個四分量條件碼寄存器CC,三條轉(zhuǎn)移指令(BRA,
CAL和RET)以及對標(biāo)號語句的支持。同時對于每一條算術(shù)指令,nvvp20還增加了一個會修改條件碼寄存器CC的對應(yīng)版本。
條件碼寄存器CC的四個分量可以是下列枚舉值之一:
GT(大于),EQ(等于),LT(小于),UN(無序)
這些分量的初始值都為EQ。當(dāng)執(zhí)行一條會修改CC寄存器的指令時,圖形處理器會根據(jù)運(yùn)算結(jié)果的每一分量與0的大小關(guān)系設(shè)置CC寄存器的相應(yīng)分量。之后轉(zhuǎn)移指令就可以根據(jù)CC寄存器的內(nèi)容確定是否進(jìn)行轉(zhuǎn)移。
轉(zhuǎn)移指令的一般格式是:
BRA <標(biāo)號> [<轉(zhuǎn)移條件>];
其中標(biāo)號是定義在著色程序中某處的標(biāo)號,標(biāo)號可以在轉(zhuǎn)移語句之前,也可以在轉(zhuǎn)移語句之后。下表是一些有效的轉(zhuǎn)移條件及其含義。
轉(zhuǎn)移條件
GT
EQ
LT.x
含義
CC寄存器的任一分量為GT時轉(zhuǎn)移
CC寄存器的任一分量為EQ時轉(zhuǎn)移
CC寄存器的x分量為LT時轉(zhuǎn)移
CC寄存器的任一分量為GT時轉(zhuǎn)移
CC寄存器的y, z, w分量中任一為LT時轉(zhuǎn)移
空 無條件轉(zhuǎn)移
(表-3.9,轉(zhuǎn)移條件)
下面是一個使用轉(zhuǎn)移指令的例子:
MOVC CC, c [0]; # c [0] = (-2, 0, 2, NaN),CC 值為(LT, EQ, GT, UN)。
BRA Label1 ();
MOV R0, R1; # 不會執(zhí)行。
Label1:
BRA Label2 ();
MOV R0, R2; # 語句會執(zhí)行。
Label2:
容易看出第一個條件轉(zhuǎn)移指令會轉(zhuǎn)移到Label1,但第二個條件轉(zhuǎn)移指令不會轉(zhuǎn)移到Label2。
過程調(diào)用語句的格式類似于轉(zhuǎn)移指令,可以無條件調(diào)用過程也可以條件調(diào)用過程。同樣過程返回指令也可以無條件或者條件返回。nvvp20限制過程調(diào)用不能超過四層,一旦圖形處理器檢測到超過四層的過程調(diào)用就會自動結(jié)束vertex program的執(zhí)行。
nvvp20還限制一個vertex program程序的所占的指令槽數(shù)不能超過256,一次運(yùn)行執(zhí)行的全部指令數(shù)不能超過64K。
我們可以把nvvp20的上述指令添加到arbvp10與arbfp10虛擬機(jī)中,構(gòu)造一個假想的arbvp20與arbfp20虛擬機(jī)做為glslang編譯器gcx的編譯目標(biāo)機(jī)器。
3.5 小結(jié)
本章介紹的四個虛擬機(jī)arbvp10、arbfp10、arbvp20與arbfp20將是glslang編譯器gcx的四個編譯目標(biāo)機(jī)器。arbvp10/arbfp10不支持轉(zhuǎn)移指令,只能從頭線性執(zhí)行著色程序;而arbvp20/arbfp20支持動態(tài)轉(zhuǎn)移指令,能夠支持復(fù)雜的控制流結(jié)構(gòu)。我們將使用不同的技術(shù)將HLSL shader轉(zhuǎn)換為可以在上述四個虛擬機(jī)上執(zhí)行的LLSL shader。
第四章 高級著色語言
4.1 概述
正如通用處理器上的軟件開發(fā)從匯編語言程序設(shè)計逐漸過渡到高級語言程序設(shè)計一樣,著色程序開發(fā)也在經(jīng)歷著同樣的過程。低級著色語言雖然能夠滿足大多數(shù)圖形應(yīng)用的需要,允許開發(fā)者寫出性能最好的著色程序,以最大程度的利用圖形處理器的硬件能力,但是它不可避免的具有下述問題:
1) 對底層圖形硬件具有強(qiáng)烈的依賴性。雖然DirectX,OpenGL等3D API可以通過
定義虛擬機(jī)抽象底層硬件的體系結(jié)構(gòu),但是正如我們所看到的,用他們編寫著色程序仍然不的不選擇某一個具體版本的低級著色語言來匹配底層的圖形硬件。
2) 低級著色語言難以學(xué)習(xí),開發(fā)效率較低。難學(xué)習(xí),難使用是匯編語言的通性,而
圖形處理器的向量體系更加增大了學(xué)習(xí)和使用的難度。
3) 無法直接利用大量現(xiàn)存的Renderman shader。
4) 不能利用廣泛使用的各種優(yōu)化編譯技術(shù),開發(fā)者必須手工優(yōu)化匯編代碼。
為此,高級著色語言進(jìn)入研究者的視野。2001年P(guān)at Hanrahan等在siggraph上提出了一個實(shí)時過程著色系統(tǒng):斯坦福著色系統(tǒng) [Pat2001]。該系統(tǒng)由三部分組成,第一部分是對可編程圖形流水線的一個抽象,第二部分是一個類似于Renderman著色語言的高級著色語言,第三部分是一個支持多后端的后端編譯器。此后不久,商業(yè)化的高級著色語言相繼出現(xiàn),它們是Cg、DirectX HLSL與和OpenGL glslang。Cg由nVidia公司和微軟公司聯(lián)合開發(fā)而成,是一種增加了向量與矩陣處理能力的類C語言。Cg的設(shè)計目標(biāo)是成為一種通用的面向硬件的語言。它既可以用來開發(fā)用于渲染的著色程序,也可以用來開發(fā)在圖形處理器上運(yùn)行的科學(xué)計算程序。Cg是一個跨平臺的高級著色語言,通過定義不同的配置(profile),Cg編譯器可以為不同的低級著色語言后端生成代碼,既支持DirectX的所有版本的低級著色語言,也支持OpenGL的所有版本的低級著色語言,同時還支持nVidia專有的所有版本的低級著色語言。DirectX HLSL類似于Cg,但是它的后端僅支持DirectX的各個版本的低級著色語言。
glslang是OpenGL Shading Language的簡稱,它是OpenGL 2.0規(guī)范的一部分,是OpenGL平臺上的高級著色語言。glslang在OpenGL管理委員會的監(jiān)督下,由3D Labs公司制定規(guī)范和提供參考實(shí)現(xiàn)。glslang的設(shè)計目標(biāo)是能夠體現(xiàn)當(dāng)前和未來圖形硬件能力,易于使用,功能強(qiáng)大,可以明顯減少日漸增加的OpenGL擴(kuò)展數(shù)目。本文的主要研究對象就是glslang及其優(yōu)化編譯技術(shù)。
4.2 glslang簡介
4.2.1 glslang程序運(yùn)行環(huán)境
glslang與OpenGL 2.0規(guī)范緊密聯(lián)系。下面是制訂中的OpenGL 2.0邏輯框圖。
(圖-4.1 OpenGL 2.0邏輯框圖)
在OpenGL 2.0中,可編程的頂點(diǎn)處理器取代了固定功能的頂點(diǎn)處理模塊;可編程的片段處理器取代了固定功能的片段處理模塊。用戶可以用glslang編寫運(yùn)行在頂點(diǎn)處理器之上的程序,稱為頂點(diǎn)著色程序(vertex program);或者用glslang編寫運(yùn)行在片斷處理器之上的程序,稱為片斷著色程序(fragment program)。當(dāng)然,用戶可以繼續(xù)使用OpenGL內(nèi)置的固定功能渲染模塊。用于編寫vertex program與fragment program的glslang略有區(qū)別,所以事是上存在兩種glslang語言。根據(jù)運(yùn)行的處理器不同,可以分為vertex glslang和fragment glslang。當(dāng)然,這兩種語言仍然具有相當(dāng)多的共性,除了一些微妙的區(qū)別,我們?nèi)匀豢梢园阉鼈兛醋魇峭环N語言。為了管理OpenGL 2.0應(yīng)用中用到的著色程序,OpenGL 2.0規(guī)范引入了program對象和shader對象的概念。運(yùn)行在頂點(diǎn)或者片斷處理器上的一個完整的程序稱為program對象,一個program對象由一個或多個shader對象組成。Shader對象是一個獨(dú)立的可編譯單元,類似于C語言中的一個源文件。與glslang語言類似,program對象與shader對象也有vertex和fragment的區(qū)別。組成program對象的各shader對象必須與被組成的program對象具有相同的類型。要在OpenGL 2.0應(yīng)用中使用program對象,首先要把組成program對象的shader對象附著到program對象之上,然后對program對象進(jìn)行編譯,之后對編譯后的program對象進(jìn)行連接。
頂點(diǎn)處理器用于進(jìn)行頂點(diǎn)變換、法向量變換與歸一化、紋理坐標(biāo)生成與變換、光照計算等操作。圖-4.2是頂點(diǎn)處理器的邏輯框圖。
(圖-4.2 頂點(diǎn)處理器邏輯框圖)
圖-4.2的左邊部分是vertex program的輸入,也即頂點(diǎn)屬性。OpenGL 2.0定義了兩種頂點(diǎn)屬性:傳統(tǒng)頂點(diǎn)屬性和一般頂點(diǎn)屬性。與arbvp10語言不同,vertex glslang中的這兩種頂點(diǎn)屬性是互不影響的。在OpenGL程序中,傳統(tǒng)頂點(diǎn)屬性通過glVertex,glNormal等設(shè)置,一般頂點(diǎn)屬性通過glVertexAttrib設(shè)置。經(jīng)優(yōu)化編譯后的vertex program中真正訪問的頂點(diǎn)屬性稱為活躍屬性(無論是傳統(tǒng)還是一般頂點(diǎn)屬性),一個vertex program中的活躍頂點(diǎn)總數(shù)不能超過MAX_VERTEX_ATTRIBS_ARB(16)。在vertex program中,傳統(tǒng)頂點(diǎn)屬性通過內(nèi)置的頂點(diǎn)屬性變量訪問,一般頂點(diǎn)屬性通過用戶定義的屬性變量訪問。圖-4.2的右邊部分是vertex program的輸出。vertex program可以通過內(nèi)置的特殊變量(special variables)和插值變量(varying variables)輸出,也可以通過用戶定義的插置變量輸出,但是不管用什么方式輸出,必須寫內(nèi)置特殊變量gl_Position。圖-4.2中間上方的uniform表示頂點(diǎn)處理器中的uniform寄存器。這些寄存器用于設(shè)置在渲染一個或多個幾何基元(primitive)時保持不變的常量值。這些值由OpenGL 2.0應(yīng)用在vertex program之外設(shè)置。用戶在vertex program中可以申明uniform變量來訪問uniform寄存器中保存的的值。OpenGL 2.0也定義了內(nèi)置uniform變量來提供對常量和OpenGL狀態(tài)變量的訪問。經(jīng)優(yōu)化編譯后的vertex program中真正用到的uniform變量稱為活躍uniform變量。活躍uniform變量所占單一浮點(diǎn)空間的的總數(shù)不能超過MAX_VERTEX_UNIFORM_COMPONENTS_ARB(512)。OpenGl 2.0對vertex
program的指令數(shù)和臨時寄存器使用數(shù)沒有限制。
片斷處理器用于進(jìn)行紋理訪問、紋理混合、霧化等操作。圖-4.3是片斷處理器的邏輯框圖。
(圖-4.3 片斷處理器邏輯框圖)
圖-4.3的左邊部分是fragment program的輸入,也即片斷屬性,片斷屬性都是插值變量。片斷屬性由光柵化模塊對vertex program或者固定頂點(diǎn)處理模塊生成的頂點(diǎn)數(shù)據(jù)進(jìn)行插值生成。片斷屬性有兩種:內(nèi)置插值變量和自定義插值變量。內(nèi)置插值變量通過表-4.7中的插值變量名訪問。自定義插值變量通過在vertex program和fragment program中定義同名插值變量訪問。圖-4.3的右邊部分是fragment program的輸出,稱為片斷輸出。片斷輸出通過表-4.8中的特殊變量名訪問。輸出值將傳遞給OpenGL 2.0渲染流水線的后續(xù)模塊進(jìn)行處理。圖-4.3中間上方的uniform與vertex program中的uniform意義相同,但是最大活躍uniform變量數(shù)為MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB(64)。OpenGL 2.0對fragment
program的指令數(shù)和臨時寄存器使用數(shù)也沒有限制。
4.2.2 glslang程序例子
圖-4.4是一個簡單的vertex program的例子:
varying vec3 Normal; // output.
#define MVP gl_ModelViewProjectionMatrix
#define MV gl_ModelViewMatrix
#define MV_IT gl_NormalMatrix
void main(void)
{
}
(圖-4.4,Vertex Program)
圖-4.5是一個簡單的fragment program的例子:
varying vec3 Normal; // input.
uniform vec3 LightColor; // Light color.
uniform vec3 LightPos; // Light position.
void main(void)
{
vec3 color = LightColor;
color *= max(0.0,dot(normalize(Normal),LightPos));
gl_FragColor = vec4(color,1.0);
}
gl_Postion = MVP * gl_Vertex;
Normal = normalize(MV_IT * gl_Normal);
(圖-4.5,F(xiàn)rgment Program)
容易看出,glslang與C語言具有極大的類似性。事實(shí)上,glslang規(guī)范就是在C語言和Renderman 著色語言的基礎(chǔ)上制定而成的,這也是其它高級著色語言所采用的策略。
4.3 glslang變量與數(shù)據(jù)類型
4.3.1 glslang數(shù)據(jù)類型
數(shù)據(jù)類型
void
bool
int
float
vec2
vec3
vec4
說明
用于申明不返回任何數(shù)據(jù)的函數(shù)
布爾類型,值為true或者fal
有符號整數(shù)
浮點(diǎn)標(biāo)量
二分量浮點(diǎn)向量
三分量浮點(diǎn)向量
四分量浮點(diǎn)向量
表-4.1列出了glslang支持的基本數(shù)據(jù)類型。
bvec2
bvec3
bvec4
ivec2
ivec3
ivec4
mat2
mat3
mat4
sampler1D
sampler2D
sampler3D
samplerCube
sampler1DShadow
二分量布爾向量
三分量布爾向量
四分量布爾向量
二分量整數(shù)向量
三分量整數(shù)向量
四分量整數(shù)向量
2×2浮點(diǎn)矩陣
3×3浮點(diǎn)矩陣
4×4浮點(diǎn)矩陣
用于訪問一維紋理
用于訪問二維紋理
用于訪問3維紋理
用于訪問立方映射紋理
用于帶比較訪問一維深度紋理
sampler2DShadow
用于帶比較訪問二維深度紋理
(表-4.1,glslang的基本數(shù)據(jù)類型)
除了表-4.1中的基本數(shù)據(jù)類型外,glslang還支持兩種聚合數(shù)據(jù)類型:結(jié)構(gòu)和數(shù)組。glslang中數(shù)據(jù)類型的語法和語義與C語言基本相同,但也存在一些的區(qū)別。在glslang中,底層硬件也許不能直接支持bool和int類型。int類型為16位精度,float精度為IEEE單精度浮點(diǎn)。Matrix類型按列存儲。結(jié)構(gòu)類型不支持匿名成員,不支持前向引用,也不支持位域,同時內(nèi)嵌定義的結(jié)構(gòu)類型局限于包含它的結(jié)構(gòu)類型之內(nèi)。數(shù)組僅支持一維數(shù)組。Sampler變量只能申明為uniform變量或者函數(shù)參數(shù),并且是只讀的,它的值由OpenGL 2.0應(yīng)用設(shè)置以綁定到具體的紋理。變量可以用與C語言類似的語法在申明時初始化,也可以用構(gòu)造器進(jìn)行初始化。下面是一些變量申明的例子:
bool bSuccess;
int i, j = 42;
float a, b = 1.5;
vec4 vColor = vec4(0.3, 0.4, 0.4. 1);
mat4 mView;
struct light
{
float intensity;
vec3 position;
};
float freqs [3];
light lights [4];
4.3.2 作用域
glslang的作用域規(guī)則與C語言相同。
4.3.3 類型修飾符
類型修飾符
const
attribute
varying
uniform
in
out
inout
說明
用于申明局部變量或者函數(shù)形參
用于申明常量類型或者只讀函數(shù)形參
用于申明頂點(diǎn)屬性變量,只用用于全局范圍
用于申明插值變量,只能用于全局范圍
用于申明不變變量,只能用于全局范圍
用于申明函數(shù)只讀形參
用于申明函數(shù)只寫形參
用于申明函數(shù)讀寫形參
表-4.2列出了glslang支持的類型修飾符(type qualifiers)。
(表-4.2,類型修飾符)
全局變量只能使用const、attribute、uniform或者varying修飾符。不使用或者使用const修飾符的全局變量可以在申明時初始化。未初始化的全局變量在進(jìn)入main函數(shù)時其值無定義。Attribute變量用于向vertex program傳遞頂點(diǎn)屬性。Varying變量由vertex program按每頂點(diǎn)設(shè)置,經(jīng)光柵化模塊插值后按每片斷傳遞給fragment program。Uniform變量用于設(shè)置程序運(yùn)行所需的外部參數(shù)和訪問OpenGL常量、狀態(tài)變量以及紋理抽樣器。局部變量只能使用const修飾符。函數(shù)形參只能使用in、out、inout和const修飾符。
4.4 glslang運(yùn)算符與表達(dá)式
glslang支持絕大多數(shù)C語言運(yùn)算符,但是不支持與指針相關(guān)的運(yùn)算符,也不支持強(qiáng)制類型轉(zhuǎn)換(cast)運(yùn)算符。glslang數(shù)組的訪問方法與支持的運(yùn)算符和C語言類似,但是數(shù)組下標(biāo)必須是整型表達(dá)式。glslang結(jié)構(gòu)的訪問方法與支持的運(yùn)算符和C語言類似,但是支持
== 與 != 運(yùn)算符。
向量類型的分量用類似于訪問結(jié)構(gòu)成員變量的方式訪問。向量的分量名如表-4.3所示。三種分量名都可以用于訪問同一個向量的分量,但是不能混合使用。也可以把向量看作是數(shù)組,用訪問數(shù)組的方式訪問。
分量名 說明
{x, y, z, w}
一般用于訪問代表位置和法向量的向量
一般用于訪問表示代表顏色的向量
{r, g, b, a}
一般用于訪問代表紋理坐標(biāo)的向量
{s, t, p, q}
(表-4.3,向量分量名)
下面是一些正確和錯誤的訪問向量分量的例子:
vec4 pos;
vec3 normal;
vec4 color;
pos.x;
;
;
// 正確
// 正確
// 正確,分量名可以置換
; // 正確,分量名可以復(fù)制,但是這種形式只能用于右值
; // 正確
pos [3]; // 正確,訪問 z 分量
; // 不正確,不能混合使用分量名
; // 不正確,normal沒有第四個分量。
矩陣的分量可以通過數(shù)組訪問方式訪問。例如:
mat4 m;
m [1]; // 訪問矩陣的第二列向量
m [0][0]; // 訪問矩陣的左上角元素
作用于向量和矩陣的一元運(yùn)算都按分量運(yùn)算。對于標(biāo)量與向量或者矩陣相乘,運(yùn)算結(jié)果是標(biāo)量乘以向量或者矩陣的每一個分量。對于向量左乘矩陣、矩陣左乘向量和矩陣乘以矩陣,按照線性代數(shù)中的向量矩陣乘法運(yùn)算。除此之外的二元運(yùn)算都是按分量運(yùn)算,且必須作用于同類型的量。
glslang引入了C++語言中的構(gòu)造器(Constructor)來進(jìn)行類型轉(zhuǎn)換和對復(fù)雜類型進(jìn)行初始化、賦值。下面是一些構(gòu)造器使用的例子:
bool b = fal;
int n = int(b); // bool 轉(zhuǎn)換成整數(shù)
float f = 0.0;
vec3 v3 = vec3(f); // 用 f 的值初始化v3的三個分量
vec4 v4 = vec4(v3,f); // v4的前三個分量初始化成v3的相應(yīng)分量,第四個分
量初始化成f
glslang的表達(dá)式類似于C語言中的表達(dá)式,但是不支持隱式類型轉(zhuǎn)換。
4.5 glslang語句與程序結(jié)構(gòu)
一個shader(glslang的編譯單元)的結(jié)構(gòu)與C語言的一個源文件類似。但是glslang也引入了一些C++語言的特性,包括用時定義變量和函數(shù)重載。
函數(shù)調(diào)用按value-return規(guī)則傳遞參數(shù)。對于in參數(shù),實(shí)參的值在調(diào)用函數(shù)時復(fù)制到函數(shù)的形參;對于out參數(shù),形參的值在函數(shù)返回時復(fù)制到實(shí)參。實(shí)參按照從左向右的順序求值。遞歸(直接或者間接)調(diào)用會導(dǎo)致未定義的結(jié)果。
glslang支持選擇語句(if,if-el),循環(huán)語句(for,while-do,do-while)和結(jié)構(gòu)化轉(zhuǎn)移語句(continue,break,return,discard),但是不支持switch語句。前述語句除了discard語句外,語法和語義與C語言中的相應(yīng)語句相同。discard語句只能用在fragment program中,執(zhí)行該語句將立刻終止對當(dāng)前片斷的處理,也不會更新幀緩沖區(qū)。
4.6 glslang內(nèi)置變量與函數(shù)
4.6.1 glslang內(nèi)置頂點(diǎn)屬性
表-4.4所列是glslang的內(nèi)置頂點(diǎn)屬性,它們都是特殊變量。Vertex program通過這些變量訪問傳統(tǒng)頂點(diǎn)屬性。
內(nèi)置頂點(diǎn)屬性
gl_Color
類型
vec4
說明
頂點(diǎn)主顏色
gl_SecondaryColor vec4
gl_Normal Vec3
頂點(diǎn)從顏色
頂點(diǎn)法向量
頂點(diǎn)坐標(biāo)
gl_Vertex vec4
gl_MultiTexCoord0 vec4
頂點(diǎn)紋理坐標(biāo),對應(yīng)紋理單元0
gl_MultiTexCoord7 vec4
頂點(diǎn)紋理坐標(biāo),對應(yīng)紋理單元7
頂點(diǎn)霧化坐標(biāo)
gl_ForCoord vec4
(表-4.4,glslang內(nèi)置頂點(diǎn)屬性)
4.6.2 glslang內(nèi)置頂點(diǎn)輸出
glslang的內(nèi)置頂點(diǎn)輸出有兩類。一類是特殊變量,見表-4.5,vertex program通過這些變量名與OpenGL 2.0的固定流水線處理模塊通訊。另一類是插值變量,見表-4.6,vertex
program通過這些變量名與OpenGL 2.0的固定流水線處理模塊和fragment program通訊。
內(nèi)置頂點(diǎn)輸出 類型 是否必須寫 說明
是 定點(diǎn)齊此空間坐標(biāo)
gl_Position vec4
否 點(diǎn)大小
gl_PointSize Float
否
gl_ClipVertex vec4
(表-4.5,glslang內(nèi)置頂點(diǎn)輸出,特殊變量)
內(nèi)置頂點(diǎn)輸出 類型 說明
gl_FrontColor vec4
正面頂點(diǎn)主顏色
gl_BackColor vec4
背面頂點(diǎn)主顏色
gl_FrontSecondaryColor vec4
正面頂點(diǎn)從顏色
gl_BackSecondaryColor vec4
背面頂點(diǎn)從顏色
gl_TexCoord [] Vec4
頂點(diǎn)紋理坐標(biāo)
gl_FogFragCoord float
頂點(diǎn)霧化坐標(biāo)
(表-4.6,glslang內(nèi)置頂點(diǎn)輸出,插值變量)
4.6.3 glslang內(nèi)置片斷屬性
表-4.7所列是內(nèi)置片斷屬性,它們都是插值變量。Fragment program 通過這些變量獲得輸入片斷的屬性。
內(nèi)置片斷屬性
gl_Color
類型
vec4
說明
片斷主顏色
gl_SecondaryColor vec4
片斷從顏色
gl_TexCoord [] vec4
片斷紋理坐標(biāo)
gl_FogFragCoord float
片斷霧化坐標(biāo)
(表-4.7,glslang內(nèi)值片斷輸入)
4.6.4 glslang內(nèi)置片斷輸出
表-4.8所列是glslang的內(nèi)置片斷輸出,它們都是特殊變量。Fragment program通過這些變量與后續(xù)的OpenGL 2.0處理模塊通訊。
內(nèi)置片斷輸出 類型
gl_FragCoord vec4
說明
片斷坐標(biāo)
gl_FrontFacing Bool
片斷所在面的朝向
片斷顏色
gl_FragColor vec4
片斷深度
gl_FragDepth Float
(表-4.8,glslang內(nèi)置片斷輸出)
4.6.5 glslang內(nèi)置常量與內(nèi)置uniform狀態(tài)變量
glslang還提供了內(nèi)值常量和內(nèi)值uniform狀態(tài)變量以允許glslang shader程序訪問OpenGL狀態(tài)和實(shí)現(xiàn)相關(guān)常量。這里不詳細(xì)列出這些變量,具體可以參考glslang規(guī)范。
4.6.6 glslang內(nèi)置函數(shù)
glslang還提供了大量用于標(biāo)量和向量操作的內(nèi)置函數(shù)。glslang shader應(yīng)當(dāng)經(jīng)量使用內(nèi)置函數(shù),因為底層的圖形硬件可以提供對這些函數(shù)硬件加速。glslang內(nèi)置函數(shù)可以分為如下幾類:三角函數(shù)、指數(shù)函數(shù)、通用函數(shù)、幾何函數(shù)、矩陣函數(shù)、向量關(guān)系函數(shù)、紋理訪問函數(shù)、片斷函數(shù)和噪音函數(shù)。這里不詳細(xì)列出,具體可以參考glslang規(guī)范。
本文發(fā)布于:2024-03-07 07:25:56,感謝您對本站的認(rèn)可!
本文鏈接:http://m.newhan.cn/zhishi/a/170976755653294.html
版權(quán)聲明:本站內(nèi)容均來自互聯(lián)網(wǎng),僅供演示用,請勿用于商業(yè)和其他非法用途。如果侵犯了您的權(quán)益請與我們聯(lián)系,我們將在24小時內(nèi)刪除。
本文word下載地址:OpenGL著色語言.doc
本文 PDF 下載地址:OpenGL著色語言.pdf
| 留言與評論(共有 0 條評論) |