4.4 幀緩沖對象
如同第一章和第二章描述的一樣,OpenGL ES渲染到幀緩沖(和從幀緩沖中讀?。?。OpenGL ES定義了兩類幀緩沖:窗口系統(tǒng)提供的幀緩沖和應用創(chuàng)建的幀緩沖。
默認情況下,OpenGL ES使用窗口系統(tǒng)提供的幀緩沖。附著在幀緩沖上的圖像的存儲,維度,空間分配,格式都是由窗口系統(tǒng)全部管理的。因此,OpenGL ES不能改變窗口系統(tǒng)提供的幀緩沖(包括其圖像)的狀態(tài),OpenGL ES也不能刪除窗口系統(tǒng)提供的幀緩沖本身或其圖像。
接下來的小節(jié)介紹的規(guī)范,可用來對應用創(chuàng)建的幀緩沖對象做創(chuàng)建,銷毀,修改狀態(tài)和附著點的操作。
應用創(chuàng)建的幀緩沖對象包含的幀緩沖的狀態(tài)和紋理對象包含紋理的狀態(tài)使用的是相同的方式。特別的是,幀緩沖對象包含了一些必要的狀態(tài),來描述顏色,深度,模板這些邏輯緩沖的集合。對每個邏輯緩沖來說,一個幀緩沖可以附著的圖像可以被附著在幀緩沖上來為邏輯緩沖存儲要被渲染的輸出。幀緩沖可附著的圖像的例子有紋理圖像和渲染緩沖圖像。
通過允許渲染緩沖圖像附著在幀緩沖上,OpenGL ES提供了一套機制來支持離屏渲染。更多的是,通過允許紋理圖像附著在幀緩沖上,OpenGL ES提供了一套機制來支持render to texture。
4.4.1 綁定和管理幀緩對象
在第四章中介紹的操作會作用于綁定在目標靶FRAMEBUFFER上的幀緩沖對象上附著的圖像。默認情況下,綁定在目標靶FRAMEBUFFER上的幀緩沖是0,并指定默認的基于實現(xiàn)的由窗口系統(tǒng)提供的幀緩沖。當綁定在目標靶FRAMEBUFFER上的幀緩沖不是0,而是應用創(chuàng)建的幀緩沖對象的名字,那么在第四章中介紹的操作就會對應用創(chuàng)建的幀緩沖對象發(fā)生作用,而不是默認的幀緩沖對象。
幀緩沖對象的命名空間是無符號整數(shù),0被OpenGL ES保留用來指代默認的幀緩沖。一個幀緩沖對象通過給FRAMEBUFFER綁定未使用的名字來創(chuàng)建。綁定的有效函數(shù)為:
void BindFramebuffer(enum target, uint framebuffer);
target要設置為FRAMEBUFFER,framebuffer設置為未使用的名字。幀緩沖對象的結果是一個有新狀態(tài)的向量。它有一個顏色附著點,再加上一個深度和模板附著點。
函數(shù)BindFramebuffer也可以用來綁定一個已經(jīng)存在的幀緩沖對象到target上。如果綁定是成功的,對于已經(jīng)綁定的幀緩沖對象其狀態(tài)不會發(fā)生任何改變,而之前綁定在target上的幀緩沖就被破壞了。當前在FRAMEBUFFER上綁定的幀緩沖可以通過GetIntegerv查詢到(FRAMEBUFFER_BINDING)。
當幀緩沖被綁定到目標靶FRAMEBUFFER上時,OpenGL ES對幀緩沖所綁定的目標靶的操作會影響附著在幀緩沖對象上的圖像,對所綁定的目標靶的查詢也會返回綁定的幀緩沖對象的狀態(tài)。特別的,在表6.21(實現(xiàn)基于像素深度)中對指定值的查詢都來自于當前的綁定的幀緩沖對象。綁定在目標靶FRAMEBUFFER上的幀緩沖對象被用作是碎片操作的目的地以及像素讀取比如ReadPixels的像素源。
在初始狀態(tài)下,保留名字0被綁定在目標靶FRAMEBUFFER上。應用創(chuàng)建的幀緩沖對象不會和名字0有關系。名字0代指窗口系統(tǒng)提供的幀緩沖對象。但名字為0綁定在目標靶FRAMEBUFFER上時,所有對幀緩沖的查詢和操作都是在默認的幀緩沖上。在一些實現(xiàn)中,默認窗口系統(tǒng)提供的幀緩沖的一些屬性可以隨著時間的變化而變化(舉個例子,比如對窗口系統(tǒng)事件的響應,比如給新的窗口繪畫系統(tǒng)附加上下文)。
應用創(chuàng)建的幀緩沖對象(就是那些名字不是0的)和默認窗口系統(tǒng)提供的幀緩沖在一些重要的地方有所不同。首先最重要的一點,不像窗口系統(tǒng)提供的幀緩沖,應用創(chuàng)建的幀緩沖在每個邏輯緩沖中都有可以被修改的附著點。幀緩沖附著的圖像可以通過這些附著點附著或者分離。其次,附著在應用創(chuàng)建的幀緩沖的圖像的大小和格式完全由OpenGL ES接口來控制,而且不會受到窗口系統(tǒng)事件的影響,比如像素格式選擇,窗口大小調整,顯示模式變化。
另外,當渲染到應用創(chuàng)建的幀緩沖或者從應用創(chuàng)建的幀緩沖中讀取時,
- 像素歸屬測試總是成功的。換句話說,應用創(chuàng)建的幀緩沖對象擁有所有他們的像素。
- 沒有可是的顏色緩沖位平面。這意味著沒有和后,前顏色位平面相關的顏色緩沖。
- 僅有的顏色緩沖位平面是那些由幀緩沖定義的,附著在附著點COLOR_ATTACHMENT0上的緩沖。
- 僅有的深度緩沖為平面是那些由幀緩沖定義的,附著在附著點DEPTH_ATTACHMENT上的緩沖。
- 僅有的模板位平面是那些由幀緩沖定義的,附著在附著點STENCIL_ATTACHMENT上的緩沖。
- 沒有多重采樣緩沖,所以依賴實現(xiàn)的狀態(tài)變量SAMPLES和SAMPLE_BUFFERS都是0。
幀緩沖對象可以用下面函數(shù)刪除:
void DeleteFramebuffers(sizei n, uint *framebuffers);
framebuffers包含了要被刪除的n個緩沖對象的名字。在幀緩沖對象被刪除后,也就沒有附著點了,名字再次變成未被使用。如果當前綁定在目標靶FRAMEBUFFER上的幀緩沖被刪除了,BindFramebuffer就會被按照目標靶FRAMEBUFFER和framebuffer為0來執(zhí)行。在framebuffers中未被使用的名字被靜默忽略,正如0值一樣。
函數(shù)
void GenFramebuffers(sizei n,uint *framebuffers);
返回n個之前沒有用過的幀緩沖對象,新的幀緩沖對象名字儲存在framebuffers中。僅僅處于GenFramebuffers的目的,這些名字會被標記為使用過,但是查詢他們的狀態(tài)和類型只有在第一次綁定后才可以,就像他們沒有被使用過一樣。
4.4.2 把圖像附著在幀緩沖上
幀緩沖可附著的圖像可以附著在應用創(chuàng)建的幀緩沖對象上或者從其分立。相反的,在窗口系統(tǒng)提供的幀緩沖的圖像附著點,不能通過OpenGL ES改變。
一個單一的幀緩沖可附著圖像可以附著在多個應用創(chuàng)建的幀緩沖對象上,這樣很好的避免了數(shù)據(jù)的拷貝和可能增加的內存消耗。
對每個邏輯緩沖,幀緩沖對象存儲了一系列的定義邏輯緩沖的附著點的狀態(tài)。附著點狀態(tài)包含了足夠多的狀態(tài),這些狀態(tài)用來標識在附著點上附著的單一圖像或者沒有圖形附著。每個邏輯緩沖的附著點狀態(tài)羅列在表6.24中。
有兩種類型的幀緩沖可附著圖像:渲染緩沖對象的圖像和紋理對象的圖像。
4.4.3 渲染緩沖對象
一個渲染緩沖是一個包含了一副殼渲染的內部格式圖像的數(shù)據(jù)存儲對象。OpenGL ES提供了描述底層的用來申請和刪除渲染緩沖的圖像的方法,以及把渲染緩沖的圖象附著在幀緩沖的方法。
渲染緩沖對象的命名空間是無符號整數(shù),0被OpenGL ES保留。一個渲染緩沖對象通過將未使用的名字綁定在RENDERBUFFER上來創(chuàng)建。綁定的函數(shù)是:
BindRenderbuffer(enum target, uint renderbuffer);
target設置為RENDERBUFFER,renderbuffer用來設置名字。如果renderbuffer不是0,生成的渲染緩沖對象就是一個新的狀態(tài)向量,它被一個大小為0的內存緩沖初始化,組成它的狀態(tài)值列在表6.23中。之前的在target上的綁定都會破裂。
函數(shù)BindRenderbuffer也可以用來綁定一個已經(jīng)存在的渲染緩沖對象。如果綁定成功,新綁定的渲染緩沖對象的狀態(tài)也不會發(fā)生變化,之前的綁定在target上的渲染緩沖對象就會破裂。
當渲染緩沖對象被綁定,在對綁定的目標靶的OpenGL ES操作會作用于綁定的渲染緩沖對象,對渲染緩沖對象綁定的目標靶的查詢會返回綁定的渲染緩沖對象的狀態(tài)。
名字0是保留的。用0不能創(chuàng)建一個渲染緩沖對象。如果renderbuffer是0,之前所任意的綁定在target上的渲染緩沖對象都會破裂,target的綁定也會恢復到初始化狀態(tài)。
在初始化狀態(tài)下,保留的名字0被綁定到RENDERBUFFER。沒有渲染緩沖對象時對應于名字0的,因此,客戶端試圖更改或者查詢在目標靶FRAMRBUFFER名字為0時的渲染緩沖狀態(tài)會產(chǎn)生錯誤。
使用GetIntegerv,當前RENDERBUFFER的綁定可以通過RENDERBUFFER_BINDING來查詢。
渲染緩沖對象調用下面函數(shù)來刪除:
void DeleteRenderbuffers(sizei n, const uint *renderbuffers);
其中,renderbuffer包含了要被刪除的n個渲染緩沖對象的名字。在渲染緩沖對象被刪除后,渲染緩沖對象就沒有內容了,名字也會再次回到未使用。如果當前綁定在RENDERBUFFER的一個渲染緩沖被刪除了,就相當于是BindRenderbuffer函數(shù)用target為RENDERBUFFER和name為0做了執(zhí)行。另外,如果渲染緩沖的圖像附著在一個幀緩沖對象上時,當刪除渲染緩沖時需要特別的注意。在renderbuffers中沒有使用的名字會被靜默的忽略,就像其值為0一樣。
函數(shù)
void GenRenderbuffers(sizei n, uint *renderbuffers);
在renderbuffers中會返回n個之前沒有使用的渲染緩沖對象的名字。這些名字僅僅對于GenRenderbuffers的目第是會被標記為已使用過,但是只有在他們被第一次綁定后才可以接受渲染緩沖的狀態(tài),否則就像是他們沒有被使用一樣。
函數(shù)
void RenderbufferStorage(enum target,enum internalformat, sizei width, sizei height);
建立了渲染緩沖對象的圖像的數(shù)據(jù)存儲,格式,以及維度。target一定是RENDERBUFFER,internalformat一定是表4.5中介紹的可渲染色彩,可渲染深度,可渲染模板格式中的一種。width和height是在渲染緩沖中的像素的維度。如果width或者height都大于MAX_RENDERBUFFER_SIZE,將會產(chǎn)生INVALID_VALUE。如果OpenGL ES不能創(chuàng)建一個需求大小的數(shù)據(jù)存儲空間,會產(chǎn)生OUT_OF_MEMORY錯誤。在調用RenderbufferStorage之后,RenderbufferStorage刪除渲染緩沖上的已經(jīng)存在的數(shù)據(jù)存儲和數(shù)據(jù)存儲的內容都是未定義的。
OpenGL ES實現(xiàn)會基于RenderbufferStorage的參數(shù)(除了target)來變通內部通道結構的空間申請,但是空間申請和選定的內部格式一定不是其他狀態(tài)的函數(shù),一旦建立也不能被修改。申請的圖像的每個通道的比特位的實際結構可以通過GetRenderbufferParameteriv來查詢。
- 將渲染緩沖圖像附著在幀緩沖上
一個渲染緩沖可以通過調用函數(shù)
void FramebufferRenderbuffer(enum target, enum attachment, enum renderbuffertarget, uint renderbuffer);
將其作為一個邏輯緩沖附著在當前綁定的幀緩沖上。target一定是FRAMEBUFFER。如果FramebufferRenderbuffer在調用時,當前的FRAMEBUFFER_BINDING的值是0,將會產(chǎn)生INVALID_OPERATION錯誤。attachment應該被設置為COLOR_ATTACHMENT0,DEPTH_ATTACHMENT,STENCIL_ATTACHMENT中的其中一個附著點。renderbuffertarget一定是RENDERBUFFER,renderbuffer應該設置要附著在幀緩沖對象上的渲染緩沖對象的名字。renderbuffer一定是0或者renderbuffertarget類型的一個已經(jīng)存在的渲染緩沖對象的名字,否則,會產(chǎn)生INVALID_OPERATION錯誤。如果renderbuffer是0,renderbuffertarget的值就會被忽略。
如果renderbuffer不是0,而且如果FramebufferRenderbuffer執(zhí)行成功,名字為renderbuffer的渲染緩沖將會被用作是邏輯緩沖,這個邏輯緩沖被當前綁定在target上的幀緩沖對象的attachment做了唯一的標識。對于指定附著點的FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值被設置為RENDERBUFFER,FRAMEBUFFER_ATTACHEMNT_OBJECT_NAME的值設置給renderbuffer。其他的由attachment指定的附著點的值的狀態(tài)都被設置到如表6.24中列出的默認值。渲染緩沖對象的狀態(tài)沒有任何改變,任何之前的綁定在幀緩沖target的幀緩沖的attachment邏輯緩沖的附著點都會分離。另一方面,附著不成功時,渲染緩沖對象或者幀緩沖對象的也不會發(fā)生變化。
在當前被綁定到target的幀緩沖中,如果有任何被attachment標記的圖像,調用FramebufferRenderbuffer,將其renderbuffer參數(shù)設置為0,將會使圖像分離。在綁定到target的對象中由attachment指定的所有附著點的狀態(tài)值通過設置他們的默認值,這些默認值列在表6.24中。
如果當前綁定的幀緩沖附著圖像時,如果渲染緩沖對象被刪除,這樣就好像是FramebufferRenderbuffer被調用,并對每個在當前綁定的幀緩沖的附著咋附著點上的圖像,設置renderbuffer為0。換句話說,這個渲染緩沖圖像第一次從當前綁定的幀緩沖的所有附著點上分離。注意,渲染緩沖圖像并沒有從任何沒有綁定的幀緩沖上分離。從沒有綁定的幀緩沖上分離圖像是應用的責任。
- 將紋理附著在幀緩沖上
OpenGL ES支持將幀緩沖的渲染的內容拷貝到紋理對象的圖像中,方式是通過使用CopyTexImage2D和CopyTexSubImage2D。另外,OpenGL ES也支持直接渲染到紋理對象的圖像上。
想要直接渲染到紋理圖像上,紋理對象指定的圖像可以當成是當前綁定的幀緩沖的一個邏輯緩沖附著,使用下面函數(shù):
void FramebufferTexture2D(enum target, enum attachment, enum textarget, uint texture,int level);
target是FRAMEBUFFER。如果在FramebufferTexture2D調用時,FRAMEBUFFER_BINDING的值是0,將會產(chǎn)生INVALID_OPERATION錯誤。attachment是幀緩沖對象的一個附著點。
如果texture是0,textarget和level參數(shù)就被忽略了。如果texture不是0,那么texture就一定會命名一個已經(jīng)存在的紋理對象,這個紋理對象帶有textarget的目標靶的,或者texture一定會命名立方體紋理,而且textarget一定是TEXTURE_CUBE_MAP_POSITIVE_X,TEXTURE_CUBE_MAP_POSITIVE_Y,TEXTURE_CUBE_MAP_POSITIVE_Z,TEXTURE_CUBE_MAP_NEGATIVE_X,TEXTURE_CUBE_MAP_NEGATIVE_Y,TEXTURE_CUBE_MAP_NEGATIVE_Z中的其中一個。否則,會產(chǎn)生INVALID_OPERATION錯誤。
level表示幀緩沖附著的紋理圖像的mipmap的等級,而且一定是0。否則會出現(xiàn)INVALID_VALUE錯誤。
如果texture不是0,textarget一定是TEXTURE_2D,TEXTURE_CUBE_MAP_POSITIVE_X,TEXTURE_CUBE_MAP_POSITIVE_Y,TEXTURE_CUBE_MAP_POSITIVE_Z,TEXTURE_CUBE_MAP_NEGATIVE_X,TEXTURE_CUBE_MAP_NEGATIVE_Y,TEXTURE_CUBE_MAP_NEGATIVE_Z中的一個。
如果texture不是0,且如果FramebufferTexture2D成功了,那么指定的紋理圖像將會被用作是邏輯緩沖,這個邏輯緩沖由當前綁定在target上的幀緩沖的attachment作為標識。指定的附著點的FRAMEBUFFER-ATTACHMENT-OBJECT-TYPE的值被設置到TEXTURE,FRAMEBUFFER_ATTACHMENT-OBJECT-NAME被設置到texture。另外,對有名字的附著點的FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL的值設置到level。如果texture是立方體貼圖紋理,那么有名的附著點的FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE的值設置到textarget。所有的由attachement只指定的附著點的所有其他狀態(tài)的值都設置為默認值,這些默認值在表6.24中列出。對于紋理對象的狀態(tài)沒有什么改變,綁定在目標靶target的幀緩沖對象的邏輯緩沖的在attachment的之前的所有附著點都破裂了。另一方面,如果,附著沒有成功,對于紋理對象或者幀緩沖對象的狀態(tài)都沒有任何變化。
函數(shù)FramebufferTexture2D的texture名字為0將會分離當前綁定在target的幀緩沖的所有attachment標識的圖像。由attachment指定的附著點的所有狀態(tài)值都被設置為如表6.24的默認值。
如果紋理對象在其圖像附著在當前綁定的幀緩沖上是被刪除,那么就好像是FramebufferTexture2D在調用時texture參數(shù)是0,作用于每個在當前綁定的幀緩沖上附著的圖像的附著點一樣。換句話說,在當前綁定的幀緩沖上的所有的附著點上第一次分離了紋理圖形。注意,紋理圖像不是從其他的幀緩沖上分離的。從其他幀緩沖對象上分離紋理圖像是由應用來負責的。
4.4.4 在紋理和幀緩沖之間的反饋循環(huán)
當紋理對象可以同時用作GL操作的源和目的時,可能會存在一個反饋回路。當存在反饋回路時,會導致無定義的行為。這一節(jié)將詳細介紹渲染反饋回路的小節(jié)(見3.7.7節(jié))和紋理復制反饋回路的小節(jié)(見3.7.2節(jié))。
- 渲染反饋回路
將紋理附著在幀緩沖對象上的機制不會阻止在繪畫的幀緩沖上附著綁定在紋理單元上的二維紋理圖像。當發(fā)生這種狀況時,訪問圖像的紋理操作將會產(chǎn)生未定義的結果,如同3.7.7節(jié)結尾介紹的那樣。這種條件導致的未定義的表現(xiàn)下面會詳細介紹。這樣未定義的紋理操作很有可能是未定的碎片處理操作留下的最終的結果,應該是要避免的。
當紋理對象是綁定的而且是可以做紋理處理時,為了避免在當前綁定的幀緩沖上附著紋理圖像,可以采用一些特殊的預防措施。OpenGL ES渲染操作寫入的像素,而當這些像素在當前綁定的紋理中被用做紋素需要同時讀取這些像素,這樣就創(chuàng)建了一個渲染反饋回路。這樣的場景下,幀緩沖會被認為是幀緩沖完整的,但是在這種狀態(tài)下,被渲染的碎片的值是未定義的。紋理采樣值也有可能是未定義的,如同3.7.7節(jié)中“渲染反饋回路”中介紹的那樣。
特別的,如果下面的所有條件都成立,被渲染的碎片的值會是未定義的:
- 紋理對象T的圖像附著在當前綁定的幀緩沖的附著點A。
- 紋理對象T當前綁定在紋理單元U上
- 當前可編程的頂點或者碎片處理狀態(tài),有可能會從綁定在紋理單元U上的紋理對象T上采樣。
當下面任意一個條件具備時,被渲染的碎片的值都會是未定義的:
- 紋理對象T的TEXTURE_MIN_FILTER的值是NEAREST或者LINEAR,且附著點A上的FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL的值是0(紋理對象的0級圖像陣列)。
- 紋理對象T的TEXTURE_MIN_FILTER的值是NEAREST_MIPMAP_NEAREST,NEAREST_MIPMAP_LINEAR,LINEAR_MIPMAP_NEAREST,LINEAR_MIPMAP_LINEAR中的一個,而且附著點A的FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL的值在紋理對象T指定的mipmap等級的范圍之內。
在這次討論中,如果活躍的碎片或者頂點著色器包含了一些可以對綁定在紋理單元U上的紋理對象T進行采樣的規(guī)范,那么綁定在紋理單元U上的紋理對象T采樣就是可能的,甚至是那些規(guī)范僅僅是在一定條件下被執(zhí)行。
- 紋理復制反饋回路
和渲染反饋回路相同,紋理圖像是被附著在讀入幀緩沖上的,同時又是CopyTexImage操作的目的地,如同3.7.2節(jié)中“紋理復制反饋回路”中介紹的那樣,也是有可能的。當條件成立時,復制操作對紋素的寫入和在可能存在的讀幀緩沖中用作像素使用時,對這些紋素的讀取,會形成一個紋理復制反饋回路。這種場景下,復制操作寫入的紋素的值是未定義的。
具體的,如果下面的條件成立,復制的紋素的值是無定義的:
- 紋理對象T的圖像附著在當前綁定的幀緩沖對象的附著點A。
- 選擇的讀緩沖是附著點A。
- T被綁定到
CopyTexImage操作的紋理目標靶上。 - 復制操作的level參數(shù)選擇了附著在A上的同一張圖像。
4.4.5 幀緩沖完整性
如果幀緩沖的所有的附著圖像,要求用于渲染和讀取的所有的參數(shù),都定義一致而且滿足下面的要求,則這個幀緩沖對象被稱為是一個完整的幀緩沖。幀緩沖完整性的規(guī)則是基于附著圖像的性質,和一些依賴于實現(xiàn)的約束的。如果想要幀緩沖被高效的用作OpenGL ES幀緩沖的渲染操作的目的和OpenGL ES幀緩沖的讀取操作源,那么幀緩沖必須是完整的。
附著圖像的內部格式會影響幀緩沖的完整性,所以第一次定義圖像的內部格式和可以被附著的附著點是非常有用的。圖像的內部格式在表4.5中有總結。顏色可渲染的個是包括紅,綠,藍和可能的透明度通道;深度可渲染的格式包括深度通道;模板可渲染的格式包括模板通道。
不在表4.5中列出的格式,包括壓縮的內部格式,不論他們包含了什么通道,都不是顏色,深度,模板可渲染的。
- 幀緩沖附著完整性
如果幀緩沖的附著點attachment的FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值不是NONE,被稱為名為image的幀緩沖可附著圖像附著到幀緩沖的附著點上。image通過attachment中的狀態(tài)來標識,如同在4.4.2節(jié)中介紹的。
幀緩沖附著點attachment在attachment的FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE是NONE時(比如沒有附著圖像),或者下面所有的條件都成立時,被認為是具備幀緩沖附著完整性:
- image是已經(jīng)存在的對象的一部分,其中這個對象的名字由FRAMEBUFFER_ATTACHMENT_OBJECT_NAME指定,類型由FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE指定。
- image的寬和高一定是非零的。
- 如果attachment是COLOR_ATTACHMENT0,image一定有一個顏色可渲染的內部格式。
- 如果attachment是DEPTH_ATTACHMENT,image一定有一個深度可渲染的內部格式。
- 如果attachment是STENCEL_ATTACHMENT,image一定有一個模板可渲染的內部格式。
- 幀緩沖完整性
在這一節(jié),每個規(guī)則后面都有一個粗體的錯誤枚舉。
如果是窗口系統(tǒng)提供的幀緩沖或者下面所有的條件成立,幀緩沖對象target被認為是幀緩沖完備的:
- 所有幀緩沖附著點是幀緩沖附著點完備的。FRAMEBUFFER_INCOMPLETE_ATTACHMENT
- 在幀緩沖上至少一副圖像時附著的。FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
- 所有附著的圖像有相同的寬和高。FRAMEBUFFER_INCOMPLETE_DIMENSIONS
- 附著圖像的內部格式的組合沒有違反基于實現(xiàn)的系列約束。FRAMEBUFFER_UNSUPPORTED
在幀緩沖完備性規(guī)則的每個條件后面的粗體枚舉,表示當違反該條件時,CheckFramebufferStatus函數(shù)產(chǎn)生的返回值。如果違反超過一個條件,確切的CheckFramebufferStatus要返回哪一條枚舉,是依賴于實現(xiàn)的。
執(zhí)行下面操作中的任何一條都有可能改變幀緩沖是否完備。
- 用
BindFramebuffer綁定到不同的幀緩沖上。 - 用
FramebufferTexture2D和FramebufferRenderbuffer將圖像附著在幀緩沖上。 - 用
FramebufferTexture2D和FramebufferRenderbuffer將圖像從幀緩沖上分離。 - 調用
TexImage2D,CopyTexImage2D,CompressedTexImage2D改變幀緩沖上附著的紋理圖像的寬,高和內部格式。 - 調用
RenderbufferStorage改變在幀緩沖上附著的渲染緩沖的寬,高和內部格式。 - 調用
DeleteTextures,DeleteRenderbuffers刪除在當前幀緩沖綁定的幀緩沖對象上附著的包含圖像的對象。
盡管OpenGl ES為幀緩沖可附著圖像定義了一系列的內部格式,比如紋理圖像和的渲染緩沖圖像,但是一些實現(xiàn)還是不能支持渲染一些特殊的內部格式組合。如果在幀緩沖對象上附著的圖像的格式的組合并不被實現(xiàn)所支持,那么幀緩沖就是不完備的,產(chǎn)生條件標簽FRAMEBUFFER_UNSUPPORTED下。對于不產(chǎn)生FRAMEBUFFER_UNSUPPORTED的幀緩沖,必然至少會有一種內部格式的組合。
由于特別的幀緩沖完備性測試的依賴于實現(xiàn)的條件,和因為幀緩沖完備性可以在附著的圖像做修改時發(fā)生變化,盡管不是強制要求,但還是強烈建議應用要在渲染之前去檢查幀緩沖是否是完備的。當前綁定在target上的幀緩沖對象的狀態(tài)可以通過下面函數(shù)查詢:
enum CheckFramebufferStatus(enum target);
如果target不是FRAMEBUFFER,會產(chǎn)生INVALID_ENUM。如果CheckFramebufferStatus產(chǎn)生錯誤,會返回0。
否則,會返回一個標識綁定在target的幀緩沖是否完備的枚舉值,如果不是完備的,枚舉會標識出幀緩沖完備性違反的規(guī)則。如果這緩沖是完備的,那么會返回FRAMEBUFFER_COMPLETE。
- 幀緩沖完備性對幀緩沖操作的影響
如果當前綁定的幀緩沖不是完備的,那么企圖使用幀緩沖用來讀寫會產(chǎn)生錯誤。這意味著渲染函數(shù)例如DrawArrays和DrawElements,還有幀緩沖讀取函數(shù)ReadPixels和CopyTexSubImage,在幀緩沖不完整是,會產(chǎn)生INVALID_FRAMEBUFFER_OPERATION錯誤。
4.4.6 幀緩沖狀態(tài)對幀緩沖相關值的影響
當FRAMEBUFFER_BINDING的值發(fā)生變化,當前綁定的幀緩沖對象的狀態(tài)發(fā)生變化,或者當前綁定的幀緩沖上附著的圖像發(fā)生變化時,表6.21(依賴實現(xiàn)的像素深度)列出的狀態(tài)變量的值也會發(fā)生變化。
當FRAMEBUFFER_BINDING是0,在表6.21中列出的狀態(tài)變量的值是由實現(xiàn)來定義的。
當FRAMEBUFFER_BINDING是非零,如果當前綁定幀緩沖對象不是完備的幀緩沖,那么表6.21中列出的狀態(tài)變量將是未定義的。
當FRAMEBUFFER_BINDING是非零而且當前綁定的幀緩沖是完備的,那么在表6.21中列出的狀態(tài)變量的值,將完全由由FRAMEBUFFER_BINDING,當前綁定的幀緩沖的狀態(tài),和當前幀緩沖附著的圖像的狀態(tài)決定。
4.4.7 附著圖像中像素和元素之間的映射
當FRAMEBUFFER_BINDING是非零的,寫入幀緩沖的操作會改變附著在被選擇的邏輯緩沖上的附著的圖像,從幀緩沖中讀取的操作讀取在選中的邏輯緩沖上附著的圖像。
如果附著的圖像是一個渲染緩沖圖像,那么窗口坐標對應于在同樣坐標系的渲染緩沖的圖像的值。
如果附著的圖像時紋理圖像,那么窗口坐標對應于紋理0級圖像陣列的在相同組標下的值。
- 轉換成幀緩沖可附著圖像通道
當FRAMEBUFFER_BINDING是非零,顏色值可以寫入到幀緩沖時,對于每個繪圖緩沖,R,G,B,A值被轉換成被選中的邏輯緩沖上附著的幀緩沖附著圖像的內部格式對應的內部通道,得出的內部通道被下載附著在邏輯緩沖的圖像上。ColorMask,DepthMask,StencilMask,StencilMaskSeparate這些蒙版操作同樣有效。
4.4.8 錯誤
如果CheckFramebufferStatus不是FRAMEBUFFER_COMPLETE,任何企圖渲染到幀緩沖或者從幀緩沖中讀取的操作都會產(chǎn)生INVALID_FRAMEBUFFER_OPERATION錯誤。
當FRAMEBUFFER_BINDING的值是0,GetFramebufferAttachmentParameteriv調用時,會產(chǎn)生INVALID_OPERATION錯誤。
當FRAMEBUFFER_BINDING的值是0,FramebufferRenderbuffer,FramebufferTexture2D調用時,會產(chǎn)生INVALID_OPERATION錯誤。
當FRAMEBUFFER_BINDING的值是0,RenderbufferStorage調用時,會產(chǎn)生INVALID_OPERATION錯誤。
如果在調用```RenderbufferStorage``時,使用的width和height參數(shù)的值比MAX_RENDERBUFFER_SIZE大,會產(chǎn)生INVALID_VALUE錯誤。
如果在調用RenderbufferStorage時,internalformat不在支持的顏色,深度或者模板格式之中,會出現(xiàn)INVALID_ENUM錯誤。
如果在調用FramebufferRenderbuffer時,renderbuffer不是渲染緩沖對象的名字,會產(chǎn)生INVALID_OPERATION錯誤。
如果在調用FramebufferTexture2D時,texture不是紋理對象的名字,會產(chǎn)生INVALID_OPERATION錯誤。
如果在調用FramebufferTexture2D時,level比0小,會產(chǎn)生INVALID_VALUE錯誤。
如果在調用FramebufferTexture2D時,level比0大,會產(chǎn)生INVALID_VALUE錯誤。
如果在調用CheckFramebufferStatus時,target不是FRAMEBUFFER,會產(chǎn)生INNVALID_ENUM錯誤。
如果在調用RenderbufferStorage時,OpenGL ES不能創(chuàng)建一個要求大小的數(shù)據(jù)存儲空間,會產(chǎn)生OUT_OF_MEMORY錯誤。
如果在調用GenerateMipmap時,target是TEXTURE_CUBE_MAP而且當前綁定在TEXTURE_CUBE_MAP上的紋理對象不是完備的立方體,會產(chǎn)生INVALID_OPEARTION錯誤。