OpenGL幀快取物件(FBO:Frame Buffer Object) - 程式人生
文章推薦指數: 80 %
在OpenGL渲染管線中,幾何資料和紋理經過多次轉化和多次測試,最後以二維畫素的形式顯示在螢幕上。
OpenGL管線的最終渲染目的地被稱作幀快取(framebuffer ...
程式人生>>OpenGL幀快取物件(FBO:FrameBufferObject)
OpenGL幀快取物件(FBO:FrameBufferObject)
阿新••發佈:2019-01-04
翻譯的,如果不正確,敬請諒解和指正。
OpenGLFrameBufferObject(FBO)
Overview:
在OpenGL渲染管線中,幾何資料和紋理經過多次轉化和多次測試,最後以二維畫素的形式顯示在螢幕上。
OpenGL管線的最終渲染目的地被稱作幀快取(framebuffer)。
幀緩衝是一些二維陣列和OpenG所使用的儲存區的集合:顏色快取、深度快取、模板快取和累計快取。
一般情況下,幀快取完全由window系統生成和管理,由OpenGL使用。
這個預設的幀快取被稱作“window系統生成”(window-system-provided)的幀快取。
在OpenGL擴充套件中,GL_EXT_framebuffer_object提供了一種建立額外的不能顯示的幀快取物件的介面。
為了和預設的“window系統生成”的幀快取區別,這種幀緩衝成為應用程式幀快取(application-createdframebuffer)。
通過使用幀快取物件(FBO),OpenGL可以將顯示輸出到引用程式幀快取物件,而不是傳統的“window系統生成”幀快取。
而且,它完全受OpenGL控制。
相似於window系統提供的幀快取,一個FBO也包含一些儲存顏色、深度和模板資料的區域。
(注意:沒有累積快取)我們把FBO中這些邏輯快取稱之為“幀快取關聯影象”,它們是一些能夠和一個幀快取物件關聯起來的二維陣列畫素。
有兩種型別的“幀快取關聯影象”:紋理影象(textureimages)和渲染快取影象(renderbufferimages)。
如果紋理物件的影象資料關聯到幀快取,OpenGL執行的是“渲染到紋理”(rendertotexture)操作。
如果渲染快取的影象資料關聯到幀快取,OpenGL執行的是離線渲染(offscreenrendering)。
這裡要提到的是,渲染快取物件是在GL_EXT_framebuffer_object擴充套件中定義的一種新的儲存型別。
在渲染過程中它被用作儲存單幅二維影象。
下面這幅圖顯示了幀快取物件、紋理物件和渲染快取物件之間的聯絡。
多多個紋理物件或者渲染快取物件能夠通過關聯點關聯到一個幀快取物件上。
在一個幀快取物件中有多個顏色關聯點(GL_COLOR_ATTACHMENT0_EXT,...,GL_COLOR_ATTACHMENTn_EXT),一個深度關聯點(GL_DEPTH_ATTACHMENT_EXT),和一個模板關聯點(GL_STENCIL_ATTACHMENT_EXT)。
每個FBO中至少有一個顏色關聯點,其數目與實體顯示卡相關。
可以通過GL_MAX_COLOR_ATTACHMENTS_EXT來查詢顏色關聯點的最大數目。
FBO有多個顏色關聯點的原因是這樣可以同時將顏色而換成渲染到多個FBO關聯區。
這種“多渲染目標”(multiple
rendertargets,MRT)可以通過GL_ARB_draw_buffers擴充套件實現。
需要注意的是:FBO本身並沒有任何影象儲存區,只有多個關聯點。
FBO提供了一種高效的切換機制;將前面的幀快取關聯影象從FBO分離,然後把新的幀快取關聯影象關聯到FBO。
在幀快取關聯影象之間切換比在FBO之間切換要快得多。
FBO提供了glFramebufferTexture2DEXT()來切換2D紋理物件和glFramebufferRenderbufferEXT()來切換渲染快取物件。
建立FBO
建立FBO和產生VBO類似。
glGenFramebuffersEXT()
VoidgelGenFramebuffersEXT(GLsizein,GLuint*ids);
voidglDeleteFramebuffersEXT(GLsizein,constGLuint*ids);
glGenFramebuffersEXT()需要兩個引數:第一個是要建立的幀快取的數目,第二個是指向儲存一個或者多個ID的變數或陣列的指標。
它返回未使用的FBO的ID。
ID為0表示預設幀快取,即window系統提供的幀快取。
當FBO不再被使用時,FBO可以通過呼叫glDeleteFrameBuffersEXT()來刪除。
glBindFramebufferEXT()
一旦一個FBO被建立,在使用它之前必須繫結。
voidglBindFramebufferEXT(GLenumtarget,GLuintid)
第一個引數target應該是GL_FRAMEBUFFER_EXT,第二個引數是FBO的ID號。
一旦FBO被繫結,之後的所有的OpenGL操作都會對當前所繫結的FBO造成影響。
ID號為0表示預設幀快取,即預設的window提供的幀快取。
因此,在glBindFramebufferEXT()中將ID號設定為0可以解綁定當前FBO。
渲染快取物件(RenderbufferObject)
另外,渲染快取是為離線渲染而新引進的。
它允許將一個場景直接渲染到一個渲染快取物件中,而不是渲染到紋理物件中。
渲染快取物件是用於儲存單幅影象的資料儲存區域。
該影象按照一種可渲染的內部格式儲存。
它用於儲存沒有相關紋理格式的OpenGL邏輯快取,比如模板快取或者深度快取。
glGenRenderbuffersEXT()
voidglGenRenderbuffersEXT(GLsizein,GLuint*ids)
voidglDeleteRenderbuffersEXT(GLsizein,constGluint*ids)
一旦一個渲染快取被建立,它返回一個非零的正整數。
ID為0是OpenGL保留值。
glBindRenderbufferEXT()
voidglBindRenderbufferEXT(GLenumtarget,GLuintid)
和OpenGL中其他物件一樣,在引用渲染快取之前必須綁定當前渲染快取物件。
他target引數應該是GL_RENDERBUFFER_EXT。
glRenderbufferStorageEXT()
voidglRenderbufferStorageEXT(GLenumtarget,GLenuminternalFormat,
GLsizeiwidth,GLsizeiheight)
當一個渲染快取被建立,它沒有任何資料儲存區域,所以我們還要為他分配空間。
這可以通過用glRenderbufferStorageEXT()實現。
第一個引數必須是GL_RENDERBUFFER_EXT。
第二個引數可以是用於顏色的(GL_RGB,GL_RGBA,etc.),用於深度的(GL_DEPTH_COMPONENT),或者是用於模板的格式(GL_STENCIL_INDEX)。
Width和height是渲染快取影象的畫素維度。
width和height必須比GL_MAX_RENDERBUFFER_SIZE_EXT小,否則將會產生GL_UNVALID_VALUE錯誤。
glGetRenderbufferParameterivEXT()
voidglGetRenderbufferParameterivEXT(GLenumtarget,GLenumparam,GLint*value);
我們也可以得到當前繫結的渲染快取物件的一些引數。
Target應該是GL_RENDERBUFFER_EXT,第二個引數是所要得到的引數名字。
最後一個是指向儲存返回值的整型量的指標。
渲染快取的變數名有如下:
GL_RENDERBUFFER_WIDTH_EXT
GL_RENDERBUFFER_HEIGHT_EXT
GL_RENDERBUFFER_INTERNAL_FORMAT_EXT
GL_RENDERBUFFER_RED_SIZE_EXT
GL_RENDERBUFFER_GREEN_SIZE_EXT
GL_RENDERBUFFER_BLUE_SIZE_EXT
GL_RENDERBUFFER_ALPHA_SIZE_EXT
GL_RENDERBUFFER_DEPTH_SIZE_EXT
GL_RENDERBUFFER_STENCIL_SIZE_EXT
將影象和FBO關聯
FBO本身沒有影象儲存區。
我們必須幀快取關聯影象(紋理或渲染物件)關聯到FBO。
這種機制允許FBO快速地切換(分離和關聯)幀快取關聯影象。
切換幀快取關聯影象比在FBO之間切換要快得多。
而且,它節省了不必要的資料拷貝和記憶體消耗。
比如,一個紋理可以被關聯到多個FBO上,影象儲存區可以被多個FBO共享。
把2D紋理影象關聯到FBO
glFramebufferTexture2DEXT(GLenumtarget,
GLenumattachmentPoint,
GLenumtextureTarget,
GLuinttextureId,
GLint level)
glFramebufferTexture2DEXT()把一幅紋理影象關聯到一個FBO。
第一個引數一定是GL_FRAMEBUFFER_EXT,第二個引數是關聯紋理影象的關聯點。
第三個引數textureTarget在多數情況下是GL_TEXTURE_2D。
第四個引數是紋理物件的ID號。
最後一個引數是要被關聯的紋理的mipmap等級
如果引數textureId被設定為0,那麼紋理影象將會被從FBO分離。
如果紋理物件在依然關聯在FBO上時被刪除,那麼紋理物件將會自動從當前幫的FBO上分離。
然而,如果它被關聯到多個FBO上然後被刪除,那麼它將只被從繫結的FBO上分離,而不會被從其他非繫結的FBO上分離。
把渲染快取物件關聯到FBO
voidglFramebufferRenderbufferEXT(GLenumtarget,
GLenumattachmentPoint,
GLenumrenderbufferTarget,
GLuintrenderbufferId)
通過呼叫glFramebufferRenderbufferEXT()可以關聯渲染快取影象。
前兩個引數和glFramebufferTexture2DEXT()一樣。
第三個引數只能是GL_RENDERBUFFER_EXT,最後一個引數是渲染快取物件的ID號。
如果引數renderbufferId被設定為0,渲染快取影象將會從FBO的關聯點分離。
如果渲染快取影象在依然關聯在FBO上時被刪除,那麼紋理物件將會自動從當前繫結的FBO上分離,而不會從其他非繫結的FBO上分離。
檢查FBO狀態
一旦關聯影象(紋理和渲染快取)被關聯到FBO上,在執行FBO的操作之前,你必須檢查FBO的狀態,這可以通過呼叫glCheckFramebufferStatusEXT()實現。
如果這個FBObuilding完整,那麼任何繪製和讀取命令(glBegin(),glCopyTexImage2D(),etc)都會失敗。
GLenumglCheckFramebufferStatusEXT(GLenumtarget)
glCheckFramebufferStatusEXT()檢查當前幀快取的關聯影象和幀快取引數。
這個函式不能在glBegin()/glEnd()之間呼叫。
Target引數必須為GL_FRAMEBUFFER_EXT。
它返回一個非零值。
如果所有要求和準則都滿足,它返回GL_FRAMEBUFFER_COMPLETE_EXT。
否則,返回一個相關錯誤程式碼告訴我們哪條準則沒有滿足。
FBO完整性準則有:
(1)幀快取關聯影象的寬度和高度必須非零。
(2)如果一幅影象被關聯到一個顏色關聯點,那麼這幅影象必須有顏色可渲染的內部格式(GL_RGBA,GL_DEPTH_COMPONENT,GL_LUMINANCE,etc)。
(3)如果一幅被影象關聯到GL_DEPTH_ATTACHMENT_EXT,那麼這幅影象必須有深度可渲染的內部格式(GL_DEPTH_COMPONENT,GL_DEPTH_COMPONENT24_EXT,etc)。
(4)如果一幅被影象關聯到GL_STENCIL_ATTACHMENT_EXT,那麼這幅影象必須有模板可渲染的內部格式(GL_STENCIL_INDEX,GL_STENCIL_INDEX8_EXT,etc)。
(5)FBO至少有一幅影象關聯。
(6)被關聯到FBO的縮影影象必須有相同的寬度和高度。
(7)被關聯到顏色關聯點上的所有影象必須有相同的內部格式。
注意:即使以上所有條件都滿足,你的OpenGL驅動也可能不支援某些格式和引數的組合。
如果一種特別的實現不被OpenGL驅動支援,那麼glCheckFramebufferStatusEXT()返回GL_FRAMEBUFFER_UNSUPPORTED_EXT。
示例:渲染到紋理
包括渲染到紋理、只渲染到深度快取和使用模板快取渲染物件的輪廓。
有時候,你需要產生動態紋理。
比較常見的例子是產生鏡面反射效果、動態環境貼圖和陰影等效果。
動態紋理可以通過把場景渲染到紋理來實現。
渲染到紋理的一種傳統方式是將場景繪製到普通的幀快取上,然後呼叫glCopyTexSubImage2D()拷貝幀快取影象至紋理。
使用FBO,我們能夠將場景直接渲染到紋理,所以我們不必使用window系統提供的幀快取。
並且,我們能夠去除額外的資料拷貝(從幀快取到紋理);。
這個demo實現了使用FBO和不使用FBO兩種情況下渲染到紋理的操作,並且比較了效能差異。
除了能夠獲得性能上的提升,使用FBO的還有另外一個優點。
在傳統的渲染到紋理的模式中(不使用FBO),如果紋理解析度比渲染視窗的尺寸大,超出視窗區域的部分將被剪下掉。
然後,使用FBO就不會有這個問題。
你可以產生比顯示視窗大的幀快取渲染影象。
以下程式碼在渲染迴圈開始之前,對FBO和幀快取關聯影象進行了初始化。
注意只有一幅紋理影象被關聯到FBO,但是,一個深度渲染影象被關聯到FBO的深度關聯點。
實際上我們並沒有使用這個深度快取,但是FBO本身需要它進行深度測試。
如果我們不把這個深度可渲染的影象關聯到FBO,那麼由於缺少深度測試渲染輸出結果是不正確的。
如果在FBO渲染期間模板測試也是必要的,那麼也需要把額外的渲染影象和GL_STENCIL_ATTACHMENT_EXT關聯起來。
[cpp]
viewplaincopyprint?
// create a texture objectGLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); // create a renderbuffer object to store depth info
GLuint rboId; glGenRenderbuffersEXT(1, &rboId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); // create a framebuffer objectGLuint fboId; glGenFramebuffersEXT(1, &fboId); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId); // attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0); // attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); // check FBO statusGLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if(status != GL_FRAMEBUFFER_COMPLETE_EXT) fboUsed = false; // switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); ...
//createatextureobject
GLuinttextureId;
glGenTextures(1,&textureId);
glBindTexture(GL_TEXTURE_2D,textureId);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);//automaticmipmap
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,TEXTURE_WIDTH,TEXTURE_HEIGHT,0,
GL_RGBA,GL_UNSIGNED_BYTE,0);
glBindTexture(GL_TEXTURE_2D,0);
//createarenderbufferobjecttostoredepthinfo
GLuintrboId;
glGenRenderbuffersEXT(1,&rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,
TEXTURE_WIDTH,TEXTURE_HEIGHT);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);
//createaframebufferobject
GLuintfboId;
glGenFramebuffersEXT(1,&fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboId);
//attachthetexturetoFBOcolorattachmentpoint
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,textureId,0);
//attachtherenderbuffertodepthattachmentpoint
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT,rboId);
//checkFBOstatus
GLenumstatus=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status!=GL_FRAMEBUFFER_COMPLETE_EXT)
fboUsed=false;
//switchbacktowindow-system-providedframebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
...
渲染到紋理的過程和普通的繪製過程基本一樣。
我們只需要把渲染的目的地由window系統提供的幀快取改成不可顯示的應用程式建立的幀快取(FBO)就可以了。
[cpp]
viewplaincopyprint?
... // set rendering destination to FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId); // clear buffersglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw a scene to a texture directly
draw(); // unbind FBOglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // trigger mipmaps generation explicitly
// NOTE: If GL_GENERATE_MIPMAP is set to GL_TRUE, then glCopyTexSubImage2D()
// triggers mipmap generation automatically. However, the texture attached
// onto a FBO should generate mipmaps manually via glGenerateMipmapEXT().
glBindTexture(GL_TEXTURE_2D, textureId); glGenerateMipmapEXT(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); ...
...
//setrenderingdestinationtoFBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboId);
//clearbuffers
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//drawascenetoatexturedirectly
draw();
//unbindFBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
//triggermipmapsgenerationexplicitly
//NOTE:IfGL_GENERATE_MIPMAPissettoGL_TRUE,thenglCopyTexSubImage2D()
//triggersmipmapgenerationautomatically.However,thetextureattached
//ontoaFBOshouldgeneratemipmapsmanuallyviaglGenerateMipmapEXT().
glBindTexture(GL_TEXTURE_2D,textureId);
glGenerateMipmapEXT(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
...
注意到,glGenerateMipmapEXT()也是作為FBO擴充套件的一部分,用來在改變了紋理影象的基級之後顯式生成mipmap的。
如果GL_GENERATE_MIPMAP被設定為GL_TRUE,那麼glTex{Sub}Image2D()和glCopyTex{Sub}Image2D()將會啟用自動mipmap生成(在OpenGL版本1.4或者更高版本中)。
然後,當紋理基級被改變時,FBO操作不會自動產生mipmaps。
因為FBO不會呼叫glCopyTex{Sub}Image2D()來修改紋理。
因此,要產生mipmap,glGenerateMipmapEXT()必須被顯示呼叫。
英文原文:
In OpenGL
renderingpipeline,thegeometrydataandtexturesaretransformedandpassedseveraltests,andthenfinallyrenderedontoascreenas2Dpixels.ThefinalrenderingdestinationoftheOpenGLpipelineiscalled framebuffer.Framebufferisacollection
of2DarraysorstoragesutilizedbyOpenGL;colourbuffers,depthbuffer,stencilbufferandaccumulationbuffer.Bydefault,OpenGLusestheframebufferasarenderingdestinationthatiscreatedandmanagedentirelybythewindowsystem.Thisdefaultframebuffer
iscalled window-system-provided framebuffer.
TheOpenGLextension, GL_EXT_framebuffer_object providesaninterfacetocreateadditionalnon-displayableframebufferobjects(FBO).Thisframebufferiscalled application-createdframebuffer
inordertodistinguishfromthedefault window-system-provided framebuffer.Byusingframebufferobject(FBO),anOpenGLapplicationcanredirecttherenderingoutputtotheapplication-created framebufferobject(FBO)otherthanthetraditional window-system-providedframebuffer.
And,itisfullycontrolledbyOpenGL.
Similarto window-system-provided framebuffer,aFBOcontainsacollectionofrenderingdestinations;color,depthandstencilbuffer. (NotethataccumulationbufferisnotdefinedinFBO.)These
logicalbuffersinaFBOarecalled framebuffer-attachableimages,whichare2Darraysofpixelsthatcanbeattachedtoaframebufferobject.
Therearetwotypesofframebuffer-attachableimages;textureimagesandrenderbufferimages.Ifanimageofatextureobjectisattachedtoaframebuffer,OpenGLperforms "rendertotexture".
Andifanimageofarenderbufferobjectisattachedtoaframebuffer,thenOpenGLperforms "offscreenrendering".
Bytheway, renderbuffer
object isanewtypeofstorageobjectdefinedinGL_EXT_framebuffer_objectextension.Itisusedasarenderingdestinationforasingle2Dimageduringrenderingprocess.
Thefollowingdiagramshowstheconnectivityamongtheframebufferobject,textureobjectandrenderbufferobject.Multipletexture
objectsorrenderbufferobjectscanbeattachedtoaframebufferobjectthroughtheattachmentpoints。
Therearemultiplecolorattachmentpoints(GL_COLOR_ATTACHMENT0_EXT,...,GL_COLOR_ATTACHMENTn_EXT),onedepthattachmentpoint(GL_DEPTH_ATTACHMENT_EXT),andonestencilattachmentpoint(GL_STENCIL_ATTACHMENT_EXT)inaframebufferobject.
Thenumberofcolorattachmentpointsisimplementationdependent,buteachFBOmusthaveatleastonecolorattachementpoint.YoucanquerythemaximumnumberofcolorattachementpointswithGL_MAX_COLOR_ATTACHMENTS_EXT,whicharesupportedbyagraphics
card.ThereasonthataFBOhasmultiplecolorattachementpointsistoallowtorenderthecolorbuffertomultipledestinationsatthesametime.This "multiplerendertargets" (MRT)canbeaccomplishedbyGL_ARB_draw_buffers extension.
Noticethattheframebufferobjectitselfdoesnothaveanyimagestorage(array)init,but,ithasonlymultipleattachmentpoints.Thefollowingdiagramshowstheconnectivityamongtheframebufferobject,textureobjectandrenderbufferobject.Multiple
textureobjectsorrenderbufferobjectscanbeattachedtoaframebufferobjectthroughtheattachmentpoints.
Framebufferobject(FBO)providesanefficientswitchingmechanism;detachthepreviousframebuffer-attachableimagefromaFBO,andattachanewframebuffer-attachableimagetotheFBO.Switchingframebuffer-attachable
imagesismuchfasterthanswitchingbetweenFBOs.FBOprovides glFramebufferTexture2DEXT() toswitch2Dtextureobjects,andglFramebufferRenderbufferEXT() toswitchrenderbufferobjects.
CreatingFrameBufferObject(FBO)
Creatingframebufferobjectsissimilartogenerating vertex
bufferobjects(VBO).
glGenFramebuffersEXT()
voidglGenFramebuffersEXT(GLsizein,GLuint*ids)voidglDeleteFramebuffersEXT(GLsizein,constGLuint*ids)
glGenFramebuffersEXT()requires2parameters;thefirstoneisthenumberofframebufferstocreate,andthesecondparameteristhepointertoaGLuintvariableoranarraytostorea
singleIDormultipleIDs.ItreturnstheIDsofunusedframebufferobjects.ID0meansthedefaultframebuffer,whichisthewindow-system-providedframebuffer.
And,FBOmaybedeletedbycalling glDeleteFramebuffersEXT() whenitisnotusedanymore.
glBindFramebufferEXT()
OnceaFBOiscreated,ithastobeboundbeforeusingit.
voidglBindFramebufferEXT(GLenumtarget,GLuintid)
Thefirstparameter,target,shouldbeGL_FRAMEBUFFER_EXT,andthesecondparameteristheIDofaframebufferobject.OnceaFBOisbound,allOpenGLoperationsaffectontothecurrent
boundframebufferobject.TheobjectID0isreservedforthedefaultwindow-systemprovidedframebuffer.Therefore,inordertounbindthecurrentframebuffer(FBO),useID0inglBindFramebufferEXT().
RenderbufferObject
Inaddition,renderbufferobjectisnewlyintroducedforoffscreenrendering.Itallowstorenderascenedirectlytoarenderbufferobject,insteadofrenderingtoatextureobject.Renderbufferissimply
adatastorageobjectcontainingasingleimageofarenderableinternalformat.ItisusedtostoreOpenGLlogicalbuffersthatdonothavecorrespondingtextureformat,suchasstencilordepthbuffer.
glGenRenderbuffersEXT()
voidglGenRenderbuffersEXT(GLsizein,GLuint*ids)voidglDeleteRenderbuffersEXT(GLsizein,constGluint*ids)
Oncearenderbufferiscreated,itreturnsnon-zeropositiveinteger.ID0isreservedforOpenGL.
glBindRenderbufferEXT()
voidglBindRenderbufferEXT(GLenumtarget,GLuintid)
SameasotherOpenGLobjects,youhavetobindthecurrentrenderbufferobjectbeforereferencingit.ThetargetparametershouldbeGL_RENDERBUFFER_EXTforrenderbufferobject.
glRenderbufferStorageEXT()
voidglRenderbufferStorageEXT(GLenumtarget,GLenuminternalFormat,GLsizeiwidth,GLsizeiheight)
Whenarenderbufferobjectiscreated,itdoesnothaveanydatastorage,sowehavetoallocateamemoryspaceforit.ThiscanbedonebyusingglRenderbufferStorageEXT().Thefirst
parametermustbeGL_RENDERBUFFER_EXT.Thesecondparameterwouldbecolor-renderable(GL_RGB,GL_RGBA,etc.),depth-renderable(GL_DEPTH_COMPONENT),orstencil-renderableformats(GL_STENCIL_INDEX).Thewidthandheightarethedimensionoftherenderbuffer
imageinpixels.
ThewidthandheightshouldbelessthanGL_MAX_RENDERBUFFER_SIZE_EXT,otherwise,itgeneratesGL_INVALID_VALUEerror.
glGetRenderbufferParameterivEXT()
voidglGetRenderbufferParameterivEXT(GLenumtarget,GLenumparam,GLint*value);
Youalsogetvariousparametersofthecurrentlyboundrenderbufferobject. target shouldbeGL_RENDERBUFFER_EXT,andthesecondparameteristhenameofparameter.Thelastis
thepointertoanintegervariabletostorethereturnedvalue.Theavailablenamesoftherenderbufferparametersare;
GL_RENDERBUFFER_WIDTH_EXTGL_RENDERBUFFER_HEIGHT_EXTGL_RENDERBUFFER_INTERNAL_FORMAT_EXTGL_RENDERBUFFER_RED_SIZE_EXTGL_RENDERBUFFER_GREEN_SIZE_EXTGL_RENDERBUFFER_BLUE_SIZE_EXTGL_RENDERBUFFER_ALPHA_SIZE_EXTGL_RENDERBUFFER_DEPTH_SIZE_EXTGL_RENDERBUFFER_STENCIL_SIZE_EXT
AttachingimagestoFBO
FBOitselfdoesnothaveanyimagestorage(buffer)init.Instead,wemustattachframebuffer-attachableimages(textureorrenderbufferobjects)totheFBO.ThismechanismallowsthatFBOquicklyswitch
(detachandattach)theframebuffer-attachableimagesinaFBO.Itismuchfastertoswitchframebuffer-attachableimagesthantoswitchbetweenFBOs.And,itsavesunnecessarydatacopiesandmemoryconsumption.Forexample,atexturecanbeattachedtomultiple
FBOs,anditsimagestoragecanbesharedbymultipleFBOs.
Attachinga2DtextureimagetoFBO
glFramebufferTexture2DEXT(GLenumtarget,GLenumattachmentPoint,GLenumtextureTarget,GLuinttextureId,GLintlevel)
glFramebufferTexture2DEXT()istoattacha2DtextureimagetoaFBO.ThefirstparametermustbeGL_FRAMEBUFFER_EXT,andthesecondparameteristheattachmentpointwheretoconnect
thetextureimage.AFBOhasmultiplecolorattachmentpoints(GL_COLOR_ATTACHMENT0_EXT,...,GL_COLOR_ATTACHMENTn_EXT),GL_DEPTH_ATTACHMENT_EXT,andGL_STENCIL_ATTACHMENT_EXT.Thethirdparameter,"textureTarget" isGL_TEXTURE_2Dinmost
cases.Thefourthparameteristheidentifierofthetextureobject.Thelastparameteristhemipmaplevelofthetexturetobeattached.
Ifthe textureId parameterissetto0,then,thetextureimagewillbedetachedfromtheFBO.IfatextureobjectisdeletedwhileitisstillattachedtoaFBO,then,thetexture
imagewillbeautomaticallydetachedfromthecurrentlyboundFBO.However,ifitisattachedtomultipleFBOsanddeleted,thenitwillbedetachedfromonlytheboundFBO,butwillnotbedetachedfromanyotherun-boundFBOs.
AttachingaRenderbufferimagetoFBO
voidglFramebufferRenderbufferEXT(GLenumtarget,GLenumattachmentPoint,GLenumrenderbufferTarget,GLuintrenderbufferId)
ArenderbufferimagecanbeattachedbycallingglFramebufferRenderbufferEXT().ThefirstandsecondparametersaresameasglFramebufferTexture2DEXT().ThethirdparametermustbeGL_RENDERBUFFER_EXT,
andthelastparameteristheIDoftherenderbufferobject.
If renderbufferId parameterissetto0,therenderbufferimagewillbedetachedfromtheattachmentpointintheFBO.Ifarenderbufferobjectisdeletedwhileitisstillattached
inaFBO,thenitwillbeautomaticallydetachedfromtheboundFBO.However,itwillnotbedetachedfromanyothernon-boundFBOs.
CheckingFBOStatus
Onceattachableimages(texturesandrenderbuffers)areattachedtoaFBOandbeforeperformingFBOoperation,youmustvalidateiftheFBOstatusiscompleteorincompletebyusingglCheckFramebufferStatusEXT().
IftheFBOisnotcomplete,thenanydrawingandreadingcommand(glBegin(),glCopyTexImage2D(),etc)willbefailed.
GLenumglCheckFramebufferStatusEXT(GLenumtarget)
glCheckFramebufferStatusEXT()validatesallitsattachedimagesandframebufferparametersonthecurrentlyboundFBO.And,thisfunctioncannotbecalledwithinglBegin()/glEnd()pair.Thetargetparameter
shouldbeGL_FRAMEBUFFER_EXT.Itreturnsnon-zerovalueaftercheckingtheFBO.Ifallrequirementsandrulesaresatisfied,thenitreturns GL_FRAMEBUFFER_COMPLETE_EXT.Otherwise,itreturnsarelevanterrorvalue,whichtellswhatruleis
violated.
TherulesofFBOcompletenessare:
Thewidthandheightofframebuffer-attachableimagemustbenotzero.
Ifanimageisattachedtoacolorattachmentpoint,thentheimagemusthaveacolor-renderableinternalformat. (GL_RGBA,GL_DEPTH_COMPONENT,GL_LUMINANCE,etc)
IfanimageisattachedtoGL_DEPTH_ATTACHMENT_EXT,thentheimagemusthaveadepth-renderableinternalformat. (GL_DEPTH_COMPONENT,GL_DEPTH_COMPONENT24_EXT,etc)
IfanimageisattachedtoGL_STENCIL_ATTACHMENT_EXT,thentheimagemusthaveastencil-renderableinternalformat. (GL_STENCIL_INDEX,GL_STENCIL_INDEX8_EXT,etc)
FBOmusthaveatleastoneimageattached.
AllimagesattachedaFBOmusthavethesamewidthandheight.
Allimagesattachedthecolorattachmentpointsmusthavethesameinternalformat.Notethateventhoughalloftheaboveconditionsaresatisfied,yourOpenGLdrivermaynotsupportsomecombinationsofinternalformatsandparameters.Ifaparticularimplementationisnotsupported
byOpenGLdriver,thenglCheckFramebufferStatusEXT()returnsGL_FRAMEBUFFER_UNSUPPORTED_EXT.
Example:RenderToTexture
Downloadthesourceandbinary: fbo.zip Extras:
-Renderingtothedepthbufferonly: fboDepth.zip
-Renderingtheoutlinesofanobjectusingstencilbuffer: fboStencil.zip
Sometimes,youneedtogeneratedynamictexturesonthefly.Themostcommonexamplesaregeneratingmirroring/reflectioneffects,dynamiccube/environmentmapsandshadowmaps.Dynamictexturingcanbe
accomplishedbyrenderingthescenetoatexture.Atraditionalwayofrender-to-textureistodrawascenetotheframebufferasnormal,andthencopytheframebufferimagetoatexturebyusingglCopyTexSubImage2D().
UsingFBO,wecanrenderascenedirectlyontoatexture,sowedon'thavetousethewindow-system-providedframebufferatall.Furthermore,wecaneliminateanadditionaldatacopy(fromframebuffer
totexture).
Thisdemoprogramperforms rendertotexture operationwith/withoutFBO,andcomparestheperformancedifference.Otherthanperformancegain,thereisanotheradvantageofusingFBO.Ifthetexture
resolutionislargerthanthesizeoftherenderingwindowintraditionalrender-to-texturemode(withoutFBO),thentheareaoutofthewindowregionwillbeclipped.However,FBOdoesnotsufferfromthisclippingproblem.Youcancreateaframebuffer-renderable
imagelargerthanthedisplaywindow.
ThefollowingcodesistosetupaFBOandframebuffer-attachableimagesbeforetherenderingloopisstarted.NotethatnotonlyatextureimageisattachedtotheFBO,butalso,arenderbufferimageis
attachedtothedepthattachmentpointoftheFBO.Wedonotactuallyusethisdepthbuffer,however,theFBOitselfneedsitfordepthtest.Ifwedon'tattachthisdepthrenderableimagetotheFBO,thentherenderingoutputwillbecorruptedbecauseof
missingdepthtest.IfstenciltestisalsorequiredduringFBOrendering,thenadditionalrenderbufferimageshouldbeattachedtoGL_STENCIL_ATTACHMENT_EXT.
...//createatextureobjectGLuinttextureId;glGenTextures(1,&textureId);glBindTexture(GL_TEXTURE_2D,textureId);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);//automaticmipmapglTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,TEXTURE_WIDTH,TEXTURE_HEIGHT,0,GL_RGBA,GL_UNSIGNED_BYTE,0);glBindTexture(GL_TEXTURE_2D,0);//createarenderbufferobjecttostoredepthinfoGLuintrboId;glGenRenderbuffersEXT(1,&rboId);glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,rboId);glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,TEXTURE_WIDTH,TEXTURE_HEIGHT);glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);//createaframebufferobjectGLuintfboId;glGenFramebuffersEXT(1,&fboId);glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboId);//attachthetexturetoFBOcolorattachmentpointglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,textureId,0);//attachtherenderbuffertodepthattachmentpointglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,rboId);//checkFBOstatusGLenumstatus=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);if(status!=GL_FRAMEBUFFER_COMPLETE_EXT)fboUsed=false;//switchbacktowindow-system-providedframebufferglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);...
Therenderingprocedureofrender-to-textureisalmostsameasnormaldrawing.Weonlyneedtoswitchtherenderingdestinationfromthewindow-system-providedtothenon-displayable,application-created
framebuffer(FBO).
...//setrenderingdestinationtoFBOglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboId);//clearbuffersglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//drawascenetoatexturedirectlydraw();//unbindFBOglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);//triggermipmapsgenerationexplicitly//NOTE:IfGL_GENERATE_MIPMAPissettoGL_TRUE,thenglCopyTexSubImage2D()//triggersmipmapgenerationautomatically.However,thetextureattached//ontoaFBOshouldgeneratemipmapsmanuallyviaglGenerateMipmapEXT().glBindTexture(GL_TEXTURE_2D,textureId);glGenerateMipmapEXT(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D,0);...
Notethat glGenerateMipmapEXT() isalsoincludedaspartofFBOextensioninordertogeneratemipmapsexplicitlyaftermodifyingthebaseleveltextureimage.If GL_GENERATE_MIPMAP is
settoGL_TRUE,thenglTex{Sub}Image2D()andglCopyTex{Sub}Image2D()triggerautomaticmipmapgeneration(inOpenGLversion1.4orgreater).However,FBOoperationdoesnotgenerateitsmipmapsautomaticallywhenthebaseleveltextureismodifiedbecause
FBOdoesnotcallglCopyTex{Sub}Image2D()tomodifythetexture.Therefore,glGenerateMipmapEXT()mustbeexplicitlycalledformipmapgeneration.
Ifyouneedtoapostprocessingofthetexture,itispossibletocombinewith Pixel
BufferObject(PBO) tomodifythetextureefficiently.
已知A,B兩點及C點(不在直線AB上)座標,求在直線AB上距離A點距離為線段AC長度的點D座標
«上一篇
為什麼學作業系統這門課?該怎麼學?下一篇»
相關推薦
OpenGL幀快取物件(FBO:FrameBufferObject)
翻譯的,如果不正確,敬請諒解和指正。
OpenGLFrameBufferObject(FBO)
Overview:
在OpenGL渲染管線中,幾何...
【OpenGL】OpenGL幀快取物件(FBO:FrameBufferObject)
翻譯的,如果不正確,敬請諒解和指正。
OpenGLFrameBufferObject(FBO)
Overview:
...
OpenGL幀快取物件(FBO)
幀快取(Framebuffer)
幀快取是螢幕所顯示畫面的一個直接映象,又稱為位對映圖(BitMap)或光...
OpenGL渲染到幀快取物件(FBO)
視窗系統提供的幀快取是唯一可以被圖形伺服器的顯示系統所識別的幀快取。
也就是說,我們要想在螢幕上看到東西,就必須把它畫在這個視窗系統提供的幀快...
Android平臺Camera實時濾鏡實現方法探討(六)--建立幀快取物件(FBO)加速實時濾鏡處理
上一章探討了如何採用SurfaceTexture+GLSurfaceView顯示YUV資料,減少了片段著色器的工作量和程式碼...
WebGL簡易教程(十三):幀快取物件(離屏渲染)
目錄
1.概述
2.示例
2.1.著色器部分
2.2...
OpenGLES幀緩衝物件(FBO):Rendertotexture
幀緩衝物件FBO
建立幀緩衝物件
紋理附著
渲染緩衝物件附著...
FBO和FBOA離線快取物件方便高效實現累積快取功能
FBO是不使用視窗系統提供的顏色前後臺快取和輔助快取,深度快取,模板快取。
而是在OGL層面在GPU中開闢這些快取,這些快...
Redis:快取物件
首先,快取的物件有三種:
1:資料庫中單條的的資料(以表名跟id作為key永久儲存到redis),在有更新的地方都要更新快取...
Redis快取物件的實現原理
截止到目前...
搜尋
基礎教學
Mysql入門
Sql入門
Android入門
Docker入門
Go語言入門
Ruby程式入門
Python入門
Python進階
Django入門
Python爬蟲入門
最近訪問
OpenGL幀快取物件(FBO:Frame+Buffer+Object)
C語言入門--狀態機程式設計
【演算法學習】基於“平均”的隨機分配演算法(貪婪,回溯),以按平均工作量隨機分配單位為例
管理ONS(Oracle+Notification+Service)
系統技術非業餘研究+»+節點間通訊的通道微調
html常用空白符
數據結構開發(6):靜態單鏈表的實現
方差(Variance)和標準差(Standard+Deviation)
python基礎-讀取文件
從GAN到WGAN到WDGRL誤差函式的研究
延伸文章資訊
- 1OpenGL幀快取物件(FBO:Frame Buffer Object) - 程式人生
在OpenGL渲染管線中,幾何資料和紋理經過多次轉化和多次測試,最後以二維畫素的形式顯示在螢幕上。OpenGL管線的最終渲染目的地被稱作幀快取(framebuffer ...
- 2opengl Tutorial => Basics of framebuffers
Framebuffer is a type of buffer which stores color values, depth and stencil information of pixel...
- 3帧缓冲
和OpenGL中的其它对象一样,我们会使用一个叫做 glGenFramebuffers 的函数来创建一个帧缓冲对象(Framebuffer Object, FBO): unsigned int ...
- 4OpenGL Frame Buffer Object (FBO) - Song Ho Ahn
Framebuffer is a collection of 2D arrays or storages utilized by OpenGL; colour buffers, depth bu...
- 5【OpenGL】OpenGL帧缓存对象(FBO:Frame Buffer Object)
OpenGL管线的最终渲染目的地被称作帧缓存(framebuffer)。帧缓冲是一些二维数组和OpenG所使用的存储区的集合:颜色缓存、深度缓存、模板缓存和累计缓存。