How to work with framebuffers in webgl? - Stack Overflow

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

A fragment shader outputs to either the canvas or the attachments in a framebuffer. To be more terse a fragment shader outputs to a texture (internally to WebGL ... 2022DeveloperSurveyisopen!Takesurvey. Home Public Questions Tags Users Companies Collectives ExploreCollectives Teams StackOverflowforTeams –Startcollaboratingandsharingorganizationalknowledge. CreateafreeTeam WhyTeams? Teams CreatefreeTeam Collectives™onStackOverflow Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost. Learnmore Teams Q&Aforwork Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch. Learnmore Howtoworkwithframebuffersinwebgl? AskQuestion Asked 5years,4monthsago Modified 1year,10monthsago Viewed 10ktimes 4 2 IhavebeentryingtounderstandframebufferinWebGL/OpenGL-ES. Iknowthatwecanblendmultipletexturesusingframebuffer. So,tounderstandthatIwroteasamplebytakinga1*1textureandtriedtoapplyframebufferlogicontopofit. But,itdidn'twork. Seesnippetatbottom,ifyouclickon"mixredandblue",theimagesdoesn'tgetrendered,amIdoinganythingwrong? Code: ` varcanvas,gl,attrPosition,texture,program,vertexBuffer,textureBuffer,vertices,texVertices,attrPos,attrTexPos,textures=[],framebuffers=[]; canvas=document.getElementById('canvas'); gl=getWebGL(); vertices=newFloat32Array([ -1.0,-1.0, 1.0,-1.0, 1.0,1.0, -1.0,1.0, -1.0,-1.0, ]); texVertices=newFloat32Array([ 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, 0.0,0.0 ]); vargetProgram=function(){ varvs=createVertexShader([ 'attributevec2attrPos;', 'attributevec2attrTexPos;', 'varyinghighpvec2vTexCoord;', 'voidmain(){', '\tgl_Position=vec4(attrPos,0.0,1.0);', '}' ].join('\n')); varfs=createFragmentShader([ 'varyinghighpvec2vTexCoord;', 'uniformsampler2DuImage;', 'voidmain(){', '\tgl_FragColor=texture2D(uImage,vTexCoord);', '}' ].join('\n')); returncreateAndLinkPrograms(vs,fs); }; varrender=function(){ gl.clear(gl.DEPTH_BUFFER_BIT|gl.COLOR_BUFFER_BIT); gl.bindTexture(gl.TEXTURE_2D,texture); gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer); gl.vertexAttribPointer(attrPos,2,gl.FLOAT,gl.FALSE,0,0); gl.bindBuffer(gl.ARRAY_BUFFER,textureBuffer); gl.vertexAttribPointer(attrTexPos,2,gl.FLOAT,gl.FALSE,0,0); gl.drawArrays(gl.TRIANGLE_STRIP,0,5); }; if(gl){ gl.clearColor(0.1,0.5,1.0,1.0); render(); program=getProgram(); texture=createAndSetupTexture(); vertexBuffer=createAndBindBuffer(vertices,gl.ARRAY_BUFFER); attrPos=gl.getUniformLocation(program,'attrPos'); gl.enableVertexAttribArray(attrPos); textureBuffer=createAndBindBuffer(texVertices,gl.ARRAY_BUFFER); attrTexPos=gl.getUniformLocation(program,'attrTexPos'); gl.enableVertexAttribArray(attrTexPos); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,newUint8Array([123,0,60,255])); render(); } varinitPingPongTextures=function(textures,framebuffers){ for(vari=0;i<2;++i){ vartex=createAndSetupTexture(gl); textures.push(tex); //makethetexturethesamesizeastheimage gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,null); //Createaframebuffer varfbo=gl.createFramebuffer(); framebuffers.push(fbo); gl.bindFramebuffer(gl.FRAMEBUFFER,fbo); //Attachatexturetoit. gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,tex,0); } } varsetFramebuffer=function(fbo,width,height){ gl.bindFramebuffer(gl.FRAMEBUFFER,fbo); gl.viewport(0,0,width,height); }; varmixRedAndBlue=function(){ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D,texture); setFramebuffer(framebuffers[0],1,1); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,newUint8Array([255,0,0,255])); render(); gl.bindTexture(gl.TEXTURE_2D,textures[0]); setFramebuffer(framebuffers[1],1,1); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,1,1,0,gl.RGBA,gl.UNSIGNED_BYTE,newUint8Array([0,255,0,255])); render(); gl.bindTexture(gl.TEXTURE_2D,textures[1]); setFramebuffer(null,1,1); render(); };` vargetWebGLContext=function(canvas){ varwebglContextParams=['webgl','experimental-webgl','webkit-3d','moz-webgl']; varwebglContext=null; for(varindex=0;indexMixRedandblue


Edit1: Iamtryingtoachievethesameformultipleprogramswithmultiplefragmentshadersbecausehavingif/elsestatementswithinthefragmentshaderisnotrecommendedasitrunsforeachpixel. ` Shaders.prototype.VS_Base=[ 'attributevec3verticesPosition;', 'attributevec2texturePosition;', 'varyinghighpvec2vTextureCoord;', 'voidmain(void){', '\tgl_Position=vec4(verticesPosition*vec3(1.0,-1.0,1.0),0.5);', '\tvTextureCoord=texturePosition;', '}' ].join('\n'); Shaders.prototype.FS_Base_Image_RED=[ '#ifdefGL_ES', 'precisionhighpfloat;', '#endif', 'uniformsampler2DuImage;', 'varyinghighpvec2vTextureCoord;', 'voidmain(void){', '\tgl_FragColor=vec4(1.0,0.0,0.0,1.0);//texture2D(uImage,vTextureCoord);', '}' ].join('\n'); Shaders.prototype.FS_Base_Image_BLUE=[ '#ifdefGL_ES', 'precisionhighpfloat;', '#endif', 'uniformsampler2DuImage;', 'varyinghighpvec2vTextureCoord;', 'voidmain(void){', '\tgl_FragColor=vec4(0.0,0.0,1.0,1.0);//texture2D(uImage,vTextureCoord);', '}' ].join('\n');` NowIhave2separateprogramsforboththefragmentshaderandIneedtouseframebuffersformixingRedandBlue.Iamnotlookingformix()astheactualscenarioisverycomplexandthat'sthereasonIamusingmultipleprogramswithfragmentshadersforavoidingconditionalif/elsestatements. javascriptwebgl Share Follow editedFeb16,2017at6:36 graphics123 askedJan24,2017at9:34 graphics123graphics123 1,15133goldbadges1919silverbadges5050bronzebadges 1 It'snotclearwhatyou'retryingtodo.You'vegotoneshaderthatonlytakesonetextureasinput.Tomix2texturesyouneedtohave2texturesasinput. – gman Jan24,2017at15:16 Addacomment  |  1Answer 1 Sortedby: Resettodefault Highestscore(default) Datemodified(newestfirst) Datecreated(oldestfirst) 13 It'snotclearwhatyou'retryingtodo.Framebuffersarejustalistofattachments(texturesandrenderbuffers).Youusethemtorendertoatextureand/orrenderbuffer.Thenyoucanusethetextureyoujustrenderedtoasinputtosomeotherrender. Here'sanexamplewithNOframebuffers.Itblends2textures. varvs=` attributevec4position; varyingvec2v_texcoord; voidmain(){ gl_Position=position; v_texcoord=position.xy*.5+.5; } `; varfs=` precisionmediumpfloat; varyingvec2v_texcoord; uniformsampler2Dtex1; uniformsampler2Dtex2; voidmain(){ vec4color1=texture2D(tex1,v_texcoord); vec4color2=texture2D(tex2,v_texcoord); gl_FragColor=mix(color1,color2,0.5); } `; constgl=document.querySelector("canvas").getContext("webgl"); constprogram=twgl.createProgramFromSources(gl,[vs,fs]); //make2textureswithcanvas2d constctx=document.createElement("canvas").getContext("2d"); ctx.canvas.width=64; ctx.canvas.height=64; //firsttexturehasacircle ctx.fillStyle="blue"; ctx.fillRect(0,0,64,64); ctx.strokeStyle="yellow"; ctx.beginPath(); ctx.arc(32,32,20,0,Math.PI*2,false); ctx.lineWidth=12; ctx.stroke(); consttex1=createTextureFromCanvas(gl,ctx.canvas); //secondtexturehasadiamond(diagonalsquare) ctx.fillStyle="red"; ctx.fillRect(0,0,64,64); ctx.fillStyle="cyan"; ctx.beginPath(); ctx.moveTo(32,6); ctx.lineTo(58,32); ctx.lineTo(32,58); ctx.lineTo(6,32); ctx.lineTo(32,6); ctx.fill(); consttex2=createTextureFromCanvas(gl,ctx.canvas); constbuf=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,buf); gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array([ -1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1, ]),gl.STATIC_DRAW); constpositionLoc=gl.getAttribLocation(program,"position"); gl.enableVertexAttribArray(positionLoc); gl.vertexAttribPointer(positionLoc,2,gl.FLOAT,false,0,0); consttex1Loc=gl.getUniformLocation(program,"tex1"); consttex2Loc=gl.getUniformLocation(program,"tex2"); gl.useProgram(program); gl.uniform1i(tex1Loc,0); gl.uniform1i(tex2Loc,1); gl.activeTexture(gl.TEXTURE0+0); gl.bindTexture(gl.TEXTURE_2D,tex1); gl.activeTexture(gl.TEXTURE0+1); gl.bindTexture(gl.TEXTURE_2D,tex2); gl.drawArrays(gl.TRIANGLES,0,6); functioncreateTextureFromCanvas(gl,canvas){ consttex=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,tex); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,ctx.canvas); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE); returntex; } canvas{border:1pxsolidblack;} Foryourpurposethereisnodifferenceabouttheblendingpart,theonlydifferenceiswherethetexturescomefrom.Abovethetextureswerecreatedbyusinga2dcanvas.Insteadyoucanuseframebuffertorendertoatexture.AFTERyou'verenderedtoatextureyoucanthenusethattextureinsomeotherrenderjustlikeabove. Torendertoatexturefirstyoucreateaframebuffer varfb=gl.createFramebuffer(); Thenyouattachatexturetoit gl.bindFramebuffer(gl.FRAMEBUFFER,fb); gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,//attachtextureasCOLOR_ATTACHMENT0 gl.TEXTURE_2D,//attacha2Dtexture someTexture,//thetexturetoattach 0);//themipleveltorenderto(mustbe0inWebGL1) Dependingonyourattachmentsyoushouldcheckiftheywork. if(gl.checkFramebufferStatus(gl.FRAMEBUFFER)!==gl.FRAMEBUFFER_COMPLETE){ //theseattachmentsdon'twork } TheWebGLspeclists3combinationsofattachmentsthatareguaranteedtowork.Theexamplebelowisusingoneofthose3sothere'snoneedtocheck Nowifyoubindtheframebuffer gl.bindFramebuffer(gl.FRAMEBUFFER,fb); Thenwhenyoucallanygl.drawXXXfunctionorgl.clearitwillbedrawingtothesomeTextureinsteadofthecanvas.Tostartdrawingtothecanvasagainbindnull gl.bindFramebuffer(gl.FRAMEBUFFER,null); Rememberthatifthecanvasandthetexturearedifferentsizesyou'llneedtocallgl.viewporttorendercorrectly varvs=` attributevec4position; uniformmat4matrix; varyingvec2v_texcoord; voidmain(){ gl_Position=matrix*position; v_texcoord=position.xy*.5+.5; } `; varcolorFS=` precisionmediumpfloat; uniformvec4color; voidmain(){ gl_FragColor=color; } `; varmixFS=` precisionmediumpfloat; varyingvec2v_texcoord; uniformsampler2Dtex1; uniformsampler2Dtex2; voidmain(){ //probablyshouldusedifferenttexturecoordsforeach //textureformoreflexibilitybutI'mlazy vec4color1=texture2D(tex1,v_texcoord); vec4color2=texture2D(tex2,v_texcoord); gl_FragColor=mix(color1,color2,0.5); } `; constgl=document.querySelector("canvas").getContext("webgl"); constcolorProgram=twgl.createProgramFromSources(gl,[vs,colorFS]); constmixProgram=twgl.createProgramFromSources(gl,[vs,mixFS]); //make2texturesbyattachingthemtoframebuffersandrenderingtothem consttexFbPair1=createTextureAndFramebuffer(gl,64,64); consttexFbPair2=createTextureAndFramebuffer(gl,64,64); constbuf=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,buf); gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array([ -1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1, ]),gl.STATIC_DRAW); functionsetAttributes(buf,positionLoc){ gl.enableVertexAttribArray(positionLoc); gl.vertexAttribPointer(positionLoc,2,gl.FLOAT,false,0,0); } constcolorPrgPositionLoc=gl.getAttribLocation(colorProgram,"position"); setAttributes(buf,colorPrgPositionLoc); constcolorLoc=gl.getUniformLocation(colorProgram,"color"); constcolorProgMatrixLoc=gl.getUniformLocation(colorProgram,"matrix"); //drawredrecttofirsttexturethroughtheframebufferit'sattachedto gl.useProgram(colorProgram); gl.bindFramebuffer(gl.FRAMEBUFFER,texFbPair1.fb); gl.viewport(0,0,64,64); gl.uniform4fv(colorLoc,[1,0,0,1]); gl.uniformMatrix4fv(colorProgMatrixLoc,false,[ 0.5,0,0,0, 0,.25,0,0, 0,0,1,0, .2,.3,0,1, ]); gl.drawArrays(gl.TRIANGLES,0,6); //Drawabluerecttothesecondtexturethroughtheframebufferit'sattachedto gl.bindFramebuffer(gl.FRAMEBUFFER,texFbPair2.fb); gl.viewport(0,0,64,64); gl.uniform4fv(colorLoc,[0,0,1,1]); gl.uniformMatrix4fv(colorProgMatrixLoc,false,[ 0.25,0,0,0, 0,.5,0,0, 0,0,1,0, .2,.3,0,1, ]); gl.drawArrays(gl.TRIANGLES,0,6); //Drawbothtexturestothecanvas gl.bindFramebuffer(gl.FRAMEBUFFER,null); gl.viewport(0,0,gl.canvas.width,gl.canvas.height); constmixPrgPositionLoc=gl.getAttribLocation(mixProgram,"position"); setAttributes(buf,mixPrgPositionLoc); constmixProgMatrixLoc=gl.getUniformLocation(mixProgram,"matrix"); consttex1Loc=gl.getUniformLocation(mixProgram,"tex1"); consttex2Loc=gl.getUniformLocation(mixProgram,"tex2"); gl.useProgram(mixProgram); gl.uniform1i(tex1Loc,0); gl.uniform1i(tex2Loc,1); gl.activeTexture(gl.TEXTURE0+0); gl.bindTexture(gl.TEXTURE_2D,texFbPair1.tex); gl.activeTexture(gl.TEXTURE0+1); gl.bindTexture(gl.TEXTURE_2D,texFbPair2.tex); gl.uniformMatrix4fv(mixProgMatrixLoc,false,[ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, ]); gl.drawArrays(gl.TRIANGLES,0,6); functioncreateTextureAndFramebuffer(gl,width,height){ consttex=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,tex); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,null); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE); constfb=gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER,fb); gl.framebufferTexture2D( gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,tex,0); return{tex:tex,fb:fb}; } canvas{border:1pxsolidblack;} Theonlyfunctionaldifferencebetweenthefirstprogramandthesecondishowthetexturesgottheirdata.Inthefirstexamplethetexturesgottheirdatafromacanvas2d.Inthe2ndexamplethetexturesgottheirdatabyrenderingtothemusingWebGL. Asforwhyyourexampledoesn'tblendtextures,inordertoblend2texturesyouneedashaderthatusestwotextures. Share Follow editedFeb17,2017at5:24 answeredJan24,2017at16:03 gmangman 91.9k2929goldbadges230230silverbadges347347bronzebadges 6 Thanksfortheanswer,Ihavemultipleprogramsandeachprogramhasaseparatefragmentshaderandcommonvertexshader.Iamtryingtopassoutputfromonefragmentshadertoanotherfragmentshaderinanotherprogram.Canyoupleasemodifyyouranswertosupportmultipleprogramsorassistmewithsomepseudocode – graphics123 Feb16,2017at6:29 1 Afragmentshaderoutputstoeitherthecanvasortheattachmentsinaframebuffer.Tobemoreterseafragmentshaderoutputstoatexture(internallytoWebGLacanvasisreallyaframebufferwithatextureattachment).Tousetheoutputofonefragmentshaderinanothershaderyoujustusethetextureyouwrotetointhefirstfragmentshaderasinputintothesecondfragmentshader(isininthesecondfragmentshaderyoumakeauniformsampler2Dandassignitthetextureyouwrotetowhenyourenderedwiththefirstfragmentshader. – gman Feb16,2017at6:34 So,youmeantosayIcanachievethiswithoutusingframebuffers?OrIwilldefinitelyneedtheframebuffers.BecauseIdon'tknowhowtopasstheoutputofonefstoanotherfs.. – graphics123 Feb16,2017at6:39 Thesecondexamplealreadydoeswhatyou'reasking.Itcreates2programscolorProgramandmixProgram.ItusescolorProgramtowritetogl_FragColorwhichbecausewecalledgl.bindFrambuffer(texFbPair1.fb)writestopixelsintexFbPair1.textexturebecausetexFbPair1.texisattachedtotexFbPair1.fbframebuffer.Thenthesameshaderisusedwithgl.bindFramebuffer(...,texFbPair2.fb)towritetotexFBPair2.tex.FinallybothofthosetexturesarepassedtomixProgramasnormaltextures. – gman Feb16,2017at6:39 1 Youneedtheframebuffers.Byattachingatexturetoaframebufferandthenbindingthatframebufferyou'remakingtheshaderwritetothetexture.Youcanthenusethattexturewithothershadersjustlikeanynormaltexture. – gman Feb16,2017at6:44  |  Show1morecomment YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy Nottheansweryou'relookingfor?Browseotherquestionstaggedjavascriptwebgloraskyourownquestion. TheOverflowBlog Makeyouropen-sourceprojectpublicbeforeyou’reready(Ep.444) Thescienceofinterviewingdevelopers FeaturedonMeta AnnouncingthearrivalofValuedAssociate#1214:Dalmarus Improvementstositestatusandincidentcommunication RetiringOurCommunity-SpecificClosureReasonsforServerFaultandSuperUser Temporarilypausingthesitesatisfactionsurvey StagingGround:ReviewerMotivation,Scaling,andOpenQuestions Linked 2 Howtosettheread-fromandwrite-totexturesforafragmentshader? 0 WebGL-HaveMissingValuesAfterReadingFromTexture Related 4911 HowtocreateaGUID/UUID 7625 HowdoJavaScriptclosureswork? 8368 HowdoIcheckifanelementishiddeninjQuery? 7709 HowdoIredirecttoanotherwebpage? 2135 HowdoesJavaScript.prototypework? 5960 HowdoIincludeaJavaScriptfileinanotherJavaScriptfile? 5162 HowtoreplacealloccurrencesofastringinJavaScript 7416 HowtocheckwhetherastringcontainsasubstringinJavaScript? 10597 HowcanIremoveaspecificitemfromanarray? 6353 Howtoreturntheresponsefromanasynchronouscall HotNetworkQuestions Waystomakeanalienatmospherebreathable,butuncomfortable? WhydoesBendersay"Pleaseinsertgirder"? Igotninety-nineproblems-sohere'sanotherone! Currentlyself-studyingQFTandTheStandardModelbySchwartzandI'mstuckatequation1.5inPart1regardingblack-bodyradiation GAMmodelwarningmessage:stepfailureinthetaestimation Wouldn'tMiller'splanetbefriedbyblueshiftedradiation? Whatdoesthisyumpackageversionmean? WhydoesmyMOSFETalwaysburn? Non-committingauthenticatedencryptionschemesvscommittingauthenticatedencryptionschemes Inbetweenfractions Using\textsc{}manuallyinsection OutputofaHubDynamomeasuredwithanOscilloscope Isitdangeroustoconsume30mgofZinc(asZincPicolinate)perday? Againtherearesomeholesinmyplot SignalprocessinginPythonvsC++(Bandpassfilter) HowdoesHebrews11:27sayMoseswasnotafraid? Partitioningalistbasedonacriterionforsublists GapsincardinalitiesofMADfamilies Arethereany/manyUSairports(withinstrumentapproaches)stillwithoutRNAVapproaches? Can'tmultiplywidthin\newcommandforincludegraphics GameinJamesBondfilm"FromRussiawithlove" Whatdisadvantagesaretheretoencryptinganentireharddriveorahomedirectory? Movingplayerinsideofmovingspaceship? Canarunascendinglistbemade? morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-js Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?