Framebuffers - LearnOpenGL

文章推薦指數: 80 %
投票人數:10人

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<



請為這篇文章評分?