Framebuffers - LearnOpenGL
文章推薦指數: 80 %
Renderbuffer objects were introduced to OpenGL after textures as a possible type of framebuffer attachment, Just like a texture image, a renderbuffer object is ... Ifyou'rerunningAdBlock,pleaseconsiderwhitelistingthissiteifyou'dliketosupportLearnOpenGL;andnoworries,Iwon'tbemadifyoudon't:) IntroductionGettingstartedOpenGLCreatingawindowHelloWindowHelloTriangleShadersTexturesTransformationsCoordinateSystemsCameraReviewLightingColorsBasicLightingMaterialsLightingmapsLightcastersMultiplelightsReviewModelLoadingAssimpMeshModelAdvancedOpenGLDepthtestingStenciltestingBlendingFacecullingFramebuffersCubemapsAdvancedDataAdvancedGLSLGeometryShaderInstancingAntiAliasingAdvancedLightingAdvancedLightingGammaCorrectionShadowsShadowMappingPointShadowsNormalMappingParallaxMappingHDRBloomDeferredShadingSSAOPBRTheoryLightingIBLDiffuseirradianceSpecularIBLInPracticeDebuggingTextRendering2DGameBreakoutSettingupRenderingSpritesLevelsCollisionsBallCollisiondetectionCollisionresolutionParticlesPostprocessingPowerupsAudioRendertextFinalthoughtsGuestArticlesHowtopublish2020OITIntroductionWeightedBlendedSkeletalAnimation2021CSMSceneSceneGraphFrustumCullingTessellationHeightmapTessellationDSACoderepositoryTranslationsAbout BTC 1CLGKgmBSuYJ1nnvDGAepVTKNNDpUjfpRa ETH/ERC20 0x1de59bd9e52521a46309474f8372531533bd7c43 Framebuffers Advanced-OpenGL/Framebuffers Sofarwe'veusedseveraltypesofscreenbuffers:acolorbufferforwritingcolorvalues,adepthbuffertowriteandtestdepthinformation,andfinallyastencilbufferthatallowsustodiscardcertainfragmentsbasedonsomecondition.ThecombinationofthesebuffersisstoredsomewhereinGPUmemoryandiscalledaframebuffer.OpenGLgivesustheflexibilitytodefineourownframebuffersandthusdefineourowncolor(andoptionallyadepthandstencil)buffer. Therenderingoperationswe'vedonesofarwerealldoneontopoftherenderbuffersattachedtothedefaultframebuffer.Thedefaultframebufferiscreatedandconfiguredwhenyoucreateyourwindow(GLFWdoesthisforus).Bycreatingourownframebufferwecangetanadditionaltargettorenderto. Theapplicationofframebuffersmaynotimmediatelymakesense,butrenderingyourscenetoadifferentframebufferallowsustousethatresulttocreatemirrorsinascene,ordocoolpost-processingeffectsforexample.Firstwe'lldiscusshowtheyactuallyworkandthenwe'llusethembyimplementingthosecoolpost-processingeffects. Creatingaframebuffer JustlikeanyotherobjectinOpenGLwecancreateaframebufferobject(abbreviatedtoFBO)byusingafunctioncalledglGenFramebuffers: unsignedintfbo; glGenFramebuffers(1,&fbo); Thispatternofobjectcreationandusageissomethingwe'veseendozensoftimesnowsotheirusagefunctionsaresimilartoalltheotherobject'swe'veseen:firstwecreateaframebufferobject,binditastheactiveframebuffer,dosomeoperations,andunbindtheframebuffer.TobindtheframebufferweuseglBindFramebuffer: glBindFramebuffer(GL_FRAMEBUFFER,fbo); BybindingtotheGL_FRAMEBUFFERtargetallthenextreadandwriteframebufferoperationswillaffectthecurrentlyboundframebuffer.ItisalsopossibletobindaframebuffertoareadorwritetargetspecificallybybindingtoGL_READ_FRAMEBUFFERorGL_DRAW_FRAMEBUFFERrespectively.TheframebufferboundtoGL_READ_FRAMEBUFFERisthenusedforallreadoperationslikeglReadPixelsandtheframebufferboundtoGL_DRAW_FRAMEBUFFERisusedasthedestinationforrendering,clearingandotherwriteoperations.Mostofthetimesyouwon'tneedtomakethisdistinctionthoughandyougenerallybindtobothwithGL_FRAMEBUFFER. Unfortunately,wecan'tuseourframebufferyetbecauseitisnotcomplete.Foraframebuffertobecompletethefollowingrequirementshavetobesatisfied: Wehavetoattachatleastonebuffer(color,depthorstencilbuffer). Thereshouldbeatleastonecolorattachment. Allattachmentsshouldbecompleteaswell(reservedmemory). Eachbuffershouldhavethesamenumberofsamples. Don'tworryifyoudon'tknowwhatsamplesare,we'llgettothoseinalaterchapter. Fromtherequirementsitshouldbeclearthatweneedtocreatesomekindofattachmentfortheframebufferandattachthisattachmenttotheframebuffer.Afterwe'vecompletedallrequirementswecancheckifweactuallysuccessfullycompletedtheframebufferbycallingglCheckFramebufferStatuswithGL_FRAMEBUFFER.Itthenchecksthecurrentlyboundframebufferandreturnsanyofthesevaluesfoundinthespecification.IfitreturnsGL_FRAMEBUFFER_COMPLETEwe'regoodtogo: if(glCheckFramebufferStatus(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) //executevictorydance Allsubsequentrenderingoperationswillnowrendertotheattachmentsofthecurrentlyboundframebuffer.Sinceourframebufferisnotthedefaultframebuffer,therenderingcommandswillhavenoimpactonthevisualoutputofyourwindow.Forthisreasonitiscalledoff-screenrenderingwhenrenderingtoadifferentframebuffer.Ifyouwantallrenderingoperationstohaveavisualimpactagainonthemainwindowweneedtomakethedefaultframebufferactivebybindingto0: glBindFramebuffer(GL_FRAMEBUFFER,0); Whenwe'redonewithallframebufferoperations,donotforgettodeletetheframebufferobject: glDeleteFramebuffers(1,&fbo); Nowbeforethecompletenesscheckisexecutedweneedtoattachoneormoreattachmentstotheframebuffer.Anattachmentisamemorylocationthatcanactasabufferfortheframebuffer,thinkofitasanimage.Whencreatinganattachmentwehavetwooptionstotake:texturesorrenderbufferobjects. Textureattachments Whenattachingatexturetoaframebuffer,allrenderingcommandswillwritetothetextureasifitwasanormalcolor/depthorstencilbuffer.Theadvantageofusingtexturesisthattherenderoutputisstoredinsidethetextureimagethatwecantheneasilyuseinourshaders. Creatingatextureforaframebufferisroughlythesameascreatinganormaltexture: unsignedinttexture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,800,600,0,GL_RGB,GL_UNSIGNED_BYTE,NULL); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); Themaindifferenceshereisthatwesetthedimensionsequaltothescreensize(althoughthisisnotrequired)andwepassNULLasthetexture'sdataparameter.Forthistexture,we'reonlyallocatingmemoryandnotactuallyfillingit.Fillingthetexturewillhappenassoonaswerendertotheframebuffer.Alsonotethatwedonotcareaboutanyofthewrappingmethodsormipmappingsincewewon'tbeneedingthoseinmostcases. IfyouwanttorenderyourwholescreentoatextureofasmallerorlargersizeyouneedtocallglViewportagain(beforerenderingtoyourframebuffer)withthenewdimensionsofyourtexture,otherwiserendercommandswillonlyfillpartofthetexture. Nowthatwe'vecreatedatexture,thelastthingweneedtodoisactuallyattachittotheframebuffer: glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texture,0); TheglFrameBufferTexture2Dfunctionhasthefollowingparameters: target:theframebuffertypewe'retargeting(draw,readorboth). attachment:thetypeofattachmentwe'regoingtoattach.Rightnowwe'reattachingacolorattachment.Notethatthe0attheendsuggestswecanattachmorethan1colorattachment.We'llgettothatinalaterchapter. textarget:thetypeofthetextureyouwanttoattach. texture:theactualtexturetoattach. level:themipmaplevel.Wekeepthisat0. Nexttothecolorattachmentswecanalsoattachadepthandastenciltexturetotheframebufferobject.ToattachadepthattachmentwespecifytheattachmenttypeasGL_DEPTH_ATTACHMENT.Notethatthetexture'sformatandinternalformattypeshouldthenbecomeGL_DEPTH_COMPONENTtoreflectthedepthbuffer'sstorageformat.ToattachastencilbufferyouuseGL_STENCIL_ATTACHMENTasthesecondargumentandspecifythetexture'sformatsasGL_STENCIL_INDEX. Itisalsopossibletoattachbothadepthbufferandastencilbufferasasingletexture.Each32bitvalueofthetexturethencontains24bitsofdepthinformationand8bitsofstencilinformation.ToattachadepthandstencilbufferasonetextureweusetheGL_DEPTH_STENCIL_ATTACHMENTtypeandconfigurethetexture'sformatstocontaincombineddepthandstencilvalues.Anexampleofattachingadepthandstencilbufferasonetexturetotheframebufferisgivenbelow: glTexImage2D( GL_TEXTURE_2D,0,GL_DEPTH24_STENCIL8,800,600,0, GL_DEPTH_STENCIL,GL_UNSIGNED_INT_24_8,NULL ); glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_TEXTURE_2D,texture,0); Renderbufferobjectattachments RenderbufferobjectswereintroducedtoOpenGLaftertexturesasapossibletypeofframebufferattachment,Justlikeatextureimage,arenderbufferobjectisanactualbuffere.g.anarrayofbytes,integers,pixelsorwhatever.However,arenderbufferobjectcannotbedirectlyreadfrom.ThisgivesittheaddedadvantagethatOpenGLcandoafewmemoryoptimizationsthatcangiveitaperformanceedgeovertexturesforoff-screenrenderingtoaframebuffer. Renderbufferobjectsstorealltherenderdatadirectlyintotheirbufferwithoutanyconversionstotexture-specificformats,makingthemfasterasawriteablestoragemedium.Youcannotreadfromthemdirectly,butitispossibletoreadfromthemviatheslowglReadPixels.Thisreturnsaspecifiedareaofpixelsfromthecurrentlyboundframebuffer,butnotdirectlyfromtheattachmentitself. Becausetheirdataisinanativeformattheyarequitefastwhenwritingdataorcopyingdatatootherbuffers.Operationslikeswitchingbuffersarethereforequitefastwhenusingrenderbufferobjects.TheglfwSwapBuffersfunctionwe'vebeenusingattheendofeachframemayaswellbeimplementedwithrenderbufferobjects:wesimplywritetoarenderbufferimage,andswaptotheotheroneattheend.Renderbufferobjectsareperfectforthesekindofoperations. Creatingarenderbufferobjectlookssimilartotheframebuffer'scode: unsignedintrbo; glGenRenderbuffers(1,&rbo); Andsimilarlywewanttobindtherenderbufferobjectsoallsubsequentrenderbufferoperationsaffectthecurrentrbo: glBindRenderbuffer(GL_RENDERBUFFER,rbo); Sincerenderbufferobjectsarewrite-onlytheyareoftenusedasdepthandstencilattachments,sincemostofthetimewedon'treallyneedtoreadvaluesfromthem,butwedocareaboutdepthandstenciltesting.Weneedthedepthandstencilvaluesfortesting,butdon'tneedtosamplethesevaluessoarenderbufferobjectsuitsthisperfectly.Whenwe'renotsamplingfromthesebuffers,arenderbufferobjectisgenerallypreferred. CreatingadepthandstencilrenderbufferobjectisdonebycallingtheglRenderbufferStoragefunction: glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8,800,600); Creatingarenderbufferobjectissimilartotextureobjects,thedifferencebeingthatthisobjectisspecificallydesignedtobeusedasaframebufferattachment,insteadofageneralpurposedatabufferlikeatexture.Herewe'vechosenGL_DEPTH24_STENCIL8astheinternalformat,whichholdsboththedepthandstencilbufferwith24and8bitsrespectively. Thelastthinglefttodoistoactuallyattachtherenderbufferobject: glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_RENDERBUFFER,rbo); Renderbufferobjectscanbemoreefficientforuseinyouroff-screenrenderprojects,butitisimportanttorealizewhentouserenderbufferobjectsandwhentousetextures.Thegeneralruleisthatifyouneverneedtosampledatafromaspecificbuffer,itiswisetousearenderbufferobjectforthatspecificbuffer.Ifyouneedtosampledatafromaspecificbufferlikecolorsordepthvalues,youshoulduseatextureattachmentinstead. Renderingtoatexture Nowthatweknowhowframebuffers(sortof)workit'stimetoputthemtogooduse.We'regoingtorenderthesceneintoacolortextureattachedtoaframebufferobjectwecreatedandthendrawthistextureoverasimplequadthatspansthewholescreen.Thevisualoutputisthenexactlythesameaswithoutaframebuffer,butthistimeit'sallprintedontopofasinglequad.Nowwhyisthisuseful?Inthenextsectionwe'llseewhy. Firstthingtodoistocreateanactualframebufferobjectandbindit,thisisallrelativelystraightforward: unsignedintframebuffer; glGenFramebuffers(1,&framebuffer); glBindFramebuffer(GL_FRAMEBUFFER,framebuffer); Nextwecreateatextureimagethatweattachasacolorattachmenttotheframebuffer.Wesetthetexture'sdimensionsequaltothewidthandheightofthewindowandkeepitsdatauninitialized: //generatetexture unsignedinttextureColorbuffer; glGenTextures(1,&textureColorbuffer); glBindTexture(GL_TEXTURE_2D,textureColorbuffer); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,800,600,0,GL_RGB,GL_UNSIGNED_BYTE,NULL); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glBindTexture(GL_TEXTURE_2D,0); //attachittocurrentlyboundframebufferobject glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,textureColorbuffer,0); WealsowanttomakesureOpenGLisabletododepthtesting(andoptionallystenciltesting)sowehavetomakesuretoaddadepth(andstencil)attachmenttotheframebuffer.Sincewe'llonlybesamplingthecolorbufferandnottheotherbufferswecancreatearenderbufferobjectforthispurpose. Creatingarenderbufferobjectisn'ttoohard.Theonlythingwehavetorememberisthatwe'recreatingitasadepthandstencilattachmentrenderbufferobject.WesetitsinternalformattoGL_DEPTH24_STENCIL8whichisenoughprecisionforourpurposes: unsignedintrbo; glGenRenderbuffers(1,&rbo); glBindRenderbuffer(GL_RENDERBUFFER,rbo); glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8,800,600); glBindRenderbuffer(GL_RENDERBUFFER,0); Oncewe'veallocatedenoughmemoryfortherenderbufferobjectwecanunbindtherenderbuffer. Then,asafinalstepbeforewecompletetheframebuffer,weattachtherenderbufferobjecttothedepthandstencilattachmentoftheframebuffer: glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_RENDERBUFFER,rbo); Thenwewanttocheckiftheframebufferiscompleteandifit'snot,weprintanerrormessage. if(glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) std::cout<
延伸文章資訊
- 1OpenGL學習腳印: 幀緩沖對象(Frame Buffer Object) - IT閱讀
FBO中包含兩種類型的附加圖像(framebuffer-attachable): 紋理圖像和RenderBuffer圖像(texture images and renderbuffer imag...
- 2OpenGL幀快取物件(FBO:Frame Buffer Object) - 程式人生
在OpenGL渲染管線中,幾何資料和紋理經過多次轉化和多次測試,最後以二維畫素的形式顯示在螢幕上。OpenGL管線的最終渲染目的地被稱作幀快取(framebuffer ...
- 3OpenGL Frame Buffer Object (FBO) - Song Ho Ahn
Framebuffer is a collection of 2D arrays or storages utilized by OpenGL; colour buffers, depth bu...
- 4opengl Tutorial => Basics of framebuffers
Framebuffer is a type of buffer which stores color values, depth and stencil information of pixel...
- 5Framebuffer Object - OpenGL Wiki
Framebuffer Objects are OpenGL Objects, which allow for the creation of user-defined Framebuffers...