WebGL GPGPU

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

GPGPU is "General Purpose" GPU and means using the GPU for something other than drawing pixels. The basic realization to understanding GPGPU in WebGL is ... English Français 日本語 한국어 Polski Portuguese Русский 简体中文 TableofContents WebGLFundamentals.org Fix,Fork,Contribute WebGLGPGPU GPGPUis"GeneralPurpose"GPUandmeansusingtheGPUforsomething otherthandrawingpixels. ThebasicrealizationtounderstandingGPGPUinWebGListhatatexture isnotanimage,it'sa2Darrayofvalues.Inthearticleontextures wecoveredreadingfromatexture.Inthearticleonrenderingtoatexture wecoveredwritingtoatexture.So,ifrealizingatextureisa2Darrayofvalues wecansaythatwehavereallydescribedawaytoreadfromandwriteto2Darrays. ThatistheessenceofGPGPUinWebGL. InJavaScriptthereistheArray.prototype.mapfunctionwhichgivenanarraycallsafunctiononeachelement functionmultBy2(v){ returnv*2; } constsrc=[1,2,3,4,5,6]; constdst=src.map(multBy2); //dstisnow[2,4,6,8,10,12]; YoucanconsidermultBy2ashaderandmapsimilartocallinggl.drawArraysorgl.drawElements. Somedifferences. Shadersdon'tgenerateanewarray,youhavetoprovideone Wecansimulatethatbymakingourownmapfunction functionmultBy2(v){ returnv*2; } +functionmapSrcToDst(src,fn,dst){ +for(leti=0;i{ if(max===undefined){ max=min; min=0; } returnMath.random()*(max-min)+min; }; constpositions=newFloat32Array( ids.map(_=>[rand(canvas.width),rand(canvas.height),0,0]).flat()); constvelocities=newFloat32Array( ids.map(_=>[rand(-300,300),rand(-300,300),0,0]).flat()); functioncreateTexture(gl,data,width,height){ consttex=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,tex); gl.texImage2D( gl.TEXTURE_2D, 0,//miplevel gl.RGBA,//internalformat width, height, 0,//border gl.RGBA,//format gl.FLOAT,//type data, ); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST); 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; } //createatextureforthevelocityand2texturesforthepositions. constvelocityTex=createTexture(gl,velocities,particleTexWidth,particleTexHeight); constpositionTex1=createTexture(gl,positions,particleTexWidth,particleTexHeight); constpositionTex2=createTexture(gl,null,particleTexWidth,particleTexHeight); Wealsoneedframebufferslikewecoveredinthearticleonrenderingtoatexture.We'llmake2.Onethatallowsustowriteto onepositiontextureandanotherfortheotherpositiontexture. functioncreateFramebuffer(gl,tex){ constfb=gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER,fb); gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,tex,0); returnfb; } //create2framebuffers.OnethatrenderstopositionTex1one //andanotherthatrenderstopositionTex2 constpositionsFB1=createFramebuffer(gl,positionTex1); constpositionsFB2=createFramebuffer(gl,positionTex2); letoldPositionsInfo={ fb:positionsFB1, tex:positionTex1, }; letnewPositionsInfo={ fb:positionsFB2, tex:positionTex2, }; wealsoneedtosetupabufferofvertexidsforourvertexpullingparticle drawingshader. //setupanidbuffer constparticleTexWidth=20; constparticleTexHeight=10; constnumParticles=particleTexWidth*particleTexHeight; constids=newArray(numParticles).fill(0).map((_,i)=>i); constidBuffer=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,idBuffer); gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(ids),gl.STATIC_DRAW); Andweneedtocompilebothsetsofshadersandlookupallthelocations constupdatePositionProgram=webglUtils.createProgramFromSources( gl,[updatePositionVS,updatePositionFS]); constdrawParticlesProgram=webglUtils.createProgramFromSources( gl,[drawParticlesVS,drawParticlesFS]); constupdatePositionPrgLocs={ position:gl.getAttribLocation(updatePositionProgram,'position'), positionTex:gl.getUniformLocation(updatePositionProgram,'positionTex'), velocityTex:gl.getUniformLocation(updatePositionProgram,'velocityTex'), texDimensions:gl.getUniformLocation(updatePositionProgram,'texDimensions'), canvasDimensions:gl.getUniformLocation(updatePositionProgram,'canvasDimensions'), deltaTime:gl.getUniformLocation(updatePositionProgram,'deltaTime'), }; constdrawParticlesProgLocs={ id:gl.getAttribLocation(drawParticlesProgram,'id'), positionTex:gl.getUniformLocation(drawParticlesProgram,'positionTex'), texDimensions:gl.getUniformLocation(drawParticlesProgram,'texDimensions'), matrix:gl.getUniformLocation(drawParticlesProgram,'matrix'), }; Andthenatrendertime,firstwerunthepositionupdatingshadertogenerate newpositions. letthen=0; functionrender(time){ //converttoseconds time*=0.001; //Subtracttheprevioustimefromthecurrenttime constdeltaTime=time-then; //Rememberthecurrenttimeforthenextframe. then=time; webglUtils.resizeCanvasToDisplaySize(gl.canvas); //rendertothenewpositions gl.bindFramebuffer(gl.FRAMEBUFFER,newPositionsInfo.fb); gl.viewport(0,0,particleTexWidth,particleTexHeight); //setupourattributestotellWebGLhowtopull //thedatafromthebufferabovetothepositionattribute //thisbufferjustcontainsa-1to+1quadforrendering //toeverypixel gl.bindBuffer(gl.ARRAY_BUFFER,updatePositionBuffer); gl.enableVertexAttribArray(updatePositionPrgLocs.position); gl.vertexAttribPointer( updatePositionPrgLocs.position, 2,//size(numcomponents) gl.FLOAT,//typeofdatainbuffer false,//normalize 0,//stride(0=auto) 0,//offset ); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D,oldPositionsInfo.tex); gl.activeTexture(gl.TEXTURE0+1); gl.bindTexture(gl.TEXTURE_2D,velocityTex); gl.useProgram(updatePositionProgram); gl.uniform1i(updatePositionPrgLocs.positionTex,0);//telltheshaderthepositiontextureisontextureunit0 gl.uniform1i(updatePositionPrgLocs.velocityTex,1);//telltheshaderthepositiontextureisontextureunit1 gl.uniform2f(updatePositionPrgLocs.texDimensions,particleTexWidth,particleTexHeight); gl.uniform2f(updatePositionPrgLocs.canvasDimensions,gl.canvas.width,gl.canvas.height); gl.uniform1f(updatePositionPrgLocs.deltaTime,deltaTime); gl.drawArrays(gl.TRIANGLES,0,6);//draw2triangles(6vertices) Thenweusethosenewpositionstodrawpointsfortheparticles gl.bindFramebuffer(gl.FRAMEBUFFER,null); gl.viewport(0,0,gl.canvas.width,gl.canvas.height); //setupourattributestotellWebGLhowtopull //thedatafromthebufferabovetotheidattribute gl.bindBuffer(gl.ARRAY_BUFFER,idBuffer); gl.enableVertexAttribArray(drawParticlesProgLocs.id); gl.vertexAttribPointer( drawParticlesProgLocs.id, 1,//size(numcomponents) gl.FLOAT,//typeofdatainbuffer false,//normalize 0,//stride(0=auto) 0,//offset ); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D,newPositionsInfo.tex); gl.useProgram(drawParticlesProgram); gl.uniform2f(drawParticlesProgLocs.texDimensions,particleTexWidth,particleTexWidth); gl.uniform1i(drawParticlesProgLocs.positionTex,0);//telltheshaderthepositiontextureisontextureunit0 gl.uniformMatrix4fv( drawParticlesProgLocs.matrix, false, m4.orthographic(0,gl.canvas.width,0,gl.canvas.height,-1,1)); gl.drawArrays(gl.POINTS,0,numParticles); Finallyweswapthevariablestrackingtheoldandnewpositions soournewpositionsthisframewillbetheoldpositionsnextframe. //swapwhichtexturewewillreadfrom //andwhichonewewillwriteto { consttemp=oldPositionsInfo; oldPositionsInfo=newPositionsInfo; newPositionsInfo=temp; } AndwiththewegetGPGPUbasedparticles.JavaScriptisdoingalmostno workexceptcallinggl.drawArraystwice.Oncetoupdatethepositions, andoncetodrawtheparticles clickheretoopeninaseparatewindow We'redrawing200particlesbyhavingpositionandvelocitytextures20x10pixelsbig.Whatifwewantedtodraw199particles?SinceWebGLonlyworkswithtextures andtexturesare2Darrayswecan'tmakea2Darraythatis199pixels.Instead thoughwecouldcompute200butonlydraw199.You'llneedtofindsimilar solutionsforproblemsthatdon'tneatlyfitintoa2Darray. NextExample:Findingtheclosestlinesegmenttoapoint I'mnotsurethisisagoodexamplebutit'stheoneIwrote.Isayitmight notbegoodbecauseIsuspecttherearebetteralgorithmsforfinding theclosestlinetoapointthanbruteforce,checkingeverylinewiththepoint.Forexamplevariousspacepartitioningalgorithmsmightletyoueasilydiscard95% ofthepointsandsobefaster.Still,thisexampleprobablydoesshow sometechniquesofGPGPUatleast. Theproblem:Wehave500pointsand1000linesegments.Foreachpoint findwhichlinesegmentitisclosestto.Thebruteforcemethodis foreachpoint minDistanceSoFar=MAX_VALUE foreachlinesegment computedistancefrompointtolinesegment ifdistanceisi); constidBufferInfo=webglUtils.createBufferInfoFromArrays(gl,{ id:{ numComponents:1, data:ids, }, }); So,atrendertimewecomputetheresultslikewedidbeforebut wedon'tlookuptheresultswithreadPixels.Insteadwejust passthemasatexturetotheappropriateshaders. Firstwedrawallthelinesingray //drawallthelinesingray gl.bindFramebuffer(gl.FRAMEBUFFER,null); gl.viewport(0,0,gl.canvas.width,gl.canvas.height); constmatrix=m4.orthographic(0,gl.canvas.width,0,gl.canvas.height,-1,1); webglUtils.setBuffersAndAttributes(gl,drawLinesPrgInfo,idBufferInfo); gl.useProgram(drawLinesPrgInfo.program); webglUtils.setUniforms(drawLinesPrgInfo,{ linesTex, linesTexDimensions, matrix, }); gl.drawArrays(gl.LINES,0,numLineSegments*2); Thenwedrawalltheclosestlines webglUtils.setBuffersAndAttributes(gl,drawClosestLinesPrgInfo,idBufferInfo); gl.useProgram(drawClosestLinesPrgInfo.program); webglUtils.setUniforms(drawClosestLinesPrgInfo,{ numPoints, closestLinesTex, closestLinesTexDimensions, linesTex, linesTexDimensions, matrix, }); //thereisoneclosestlineforeachpoint,2verticesperline gl.drawArrays(gl.LINES,0,numPoints*2); andfinallywedraweachpoint //drawthepoints webglUtils.setBuffersAndAttributes(gl,drawPointsPrgInfo,idBufferInfo); gl.useProgram(drawPointsPrgInfo.program); webglUtils.setUniforms(drawPointsPrgInfo,{ numPoints, pointsTex, pointsTexDimensions, matrix, }); gl.drawArrays(gl.POINTS,0,numPoints); Beforewerunitletsdoonemorething.Let'saddmorepointsandlines -constpoints=[ -100,100,0,0, -200,100,0,0, -]; -constlines=[ -25,50,0,0, -25,150,0,0, -90,50,0,0, -90,150,0,0, -125,50,0,0, -125,150,0,0, -185,50,0,0, -185,150,0,0, -225,50,0,0, -225,150,0,0, -]; +functioncreatePoints(numPoints){ +constpoints=[]; +for(leti=0;iMath.random()*max; + +constpoints=createPoints(8); +constlines=createPoints(125*2); constnumPoints=points.length/4; constnumLineSegments=lines.length/4/2; andifwerunthat clickheretoopeninaseparatewindow Youcanbumpupthenumberofpointsandlines butatsomepointyouwon'tbeabletotellwhich pointsgowithwhichlinesbutwithasmallernumber youcanatleastvisuallyverifyit'sworking. Justforfun,letscombinetheparticleexampleandthis example.We'llusethetechniquesweusedtoupdate thepositionsofparticlestoupdatethepointsand linesegmentpositions. TodothatwecopyintheupdatePositionFSfragmentshader fromtheparticleexampleandcompileit.Forthevertexshader wecanusethesameoneclosestLineVSisusingasit'sjust copyinga_positiontogl_Position constclosestLinePrgInfo=webglUtils.createProgramInfo( gl,[closestLineVS,closestLineFS(numLineSegments)]); constdrawLinesPrgInfo=webglUtils.createProgramInfo( gl,[drawLinesVS,drawLinesFS]); constdrawPointsPrgInfo=webglUtils.createProgramInfo( gl,[drawPointsVS,drawClosestPointsLinesFS]); constdrawClosestLinesPrgInfo=webglUtils.createProgramInfo( gl,[drawClosestLinesVS,drawClosestPointsLinesFS]); +constupdatePositionPrgInfo=webglUtils.createProgramInfo( +gl,[closestLineVS,updatePositionFS]); Weneedtogeneratevelocitiesforboththepointsandlines -functioncreatePoints(numPoints){ +functioncreatePoints(numPoints,ranges){ constpoints=[]; for(leti=0;ir(...range)),0,0);//RGBA } returnpoints; } -constr=max=>Math.random()*max; +constr=(min,max)=>min+Math.random()*(max-min); -constpoints=createPoints(8); -constlines=createPoints(125*2); +constpoints=createPoints(8,[[0,gl.canvas.width],[0,gl.canvas.height]]); +constlines=createPoints(125*2,[[0,gl.canvas.width],[0,gl.canvas.height]]); constnumPoints=points.length/4; constnumLineSegments=lines.length/4/2; +constpointVelocities=createPoints(numPoints,[[-20,20],[-20,20]]); +constlineVelocities=createPoints(numLineSegments*2,[[-20,20],[-20,20]]); Weneedtomakecopiesofthepointsandlinestextures sowehaveoldandnewversionsofeachsowecanreadfromtheold andrendertothenew. -const{tex:pointsTex,dimensions:pointsTexDimensions}= -createDataTexture(gl,points,gl.FLOAT); -const{tex:linesTex,dimensions:linesTexDimensions}= -createDataTexture(gl,lines,gl.FLOAT); +const{tex:pointsTex1,dimensions:pointsTexDimensions1}= +createDataTexture(gl,points,gl.FLOAT); +const{tex:linesTex1,dimensions:linesTexDimensions1}= +createDataTexture(gl,lines,gl.FLOAT); +const{tex:pointsTex2,dimensions:pointsTexDimensions2}= +createDataTexture(gl,points,gl.FLOAT); +const{tex:linesTex2,dimensions:linesTexDimensions2}= +createDataTexture(gl,lines,gl.FLOAT); andweneedtexturesforthevelocities const{tex:pointVelocityTex,dimensions:pointVelocityTexDimensions}= createDataTexture(gl,pointVelocities,gl.FLOAT); const{tex:lineVelocityTex,dimensions:lineVelocityTexDimensions}= createDataTexture(gl,lineVelocities,gl.FLOAT); Weneedtomakeframebuffersforbothsetsofpointsandlines constpointsFB1=createFramebuffer(gl,pointsTex1); constpointsFB2=createFramebuffer(gl,pointsTex2); constlinesFB1=createFramebuffer(gl,linesTex1); constlinesFB2=createFramebuffer(gl,linesTex2); Andweneedtosetupsomeobjecttotrackoldandnew letoldPointsLines={ pointsFB:pointsFB1, linesFB:linesFB1, pointsTex:pointsTex1, linesTex:linesTex1, }; letnewPointsLines={ pointsFB:pointsFB2, linesFB:linesFB2, pointsTex:pointsTex2, linesTex:linesTex2, }; Thenweneedarenderloop constpointsTexDimensions=pointsTexDimensions1; constlinesTexDimensions=linesTexDimensions1; letthen=0; functionrender(time){ //converttoseconds time*=0.001; //Subtracttheprevioustimefromthecurrenttime constdeltaTime=time-then; //Rememberthecurrenttimeforthenextframe. then=time; webglUtils.resizeCanvasToDisplaySize(gl.canvas); Thefirstthingwedointherenderloopisrender thenewpositionsfromtheoldpositionsandvelocities //updatethepointpositions gl.bindFramebuffer(gl.FRAMEBUFFER,newPointsLines.pointsFB); gl.viewport(0,0,...pointsTexDimensions); webglUtils.setBuffersAndAttributes(gl,updatePositionPrgInfo,quadBufferInfo); gl.useProgram(updatePositionPrgInfo.program); webglUtils.setUniforms(updatePositionPrgInfo,{ positionTex:oldPointsLines.pointsTex, texDimensions:pointsTexDimensions, velocityTex:pointVelocityTex, canvasDimensions:[gl.canvas.width,gl.canvas.height], deltaTime, }); gl.drawArrays(gl.TRIANGLES,0,6);//drawtheclipspacequadsowegetoneresultforeachpixel anddothesameforthelinepositions //updatethelinepositions gl.bindFramebuffer(gl.FRAMEBUFFER,newPointsLines.linesFB); gl.viewport(0,0,...linesTexDimensions); webglUtils.setBuffersAndAttributes(gl,updatePositionPrgInfo,quadBufferInfo); gl.useProgram(updatePositionPrgInfo.program); webglUtils.setUniforms(updatePositionPrgInfo,{ positionTex:oldPointsLines.linesTex, texDimensions:linesTexDimensions, velocityTex:lineVelocityTex, canvasDimensions:[gl.canvas.width,gl.canvas.height], deltaTime, }); gl.drawArrays(gl.TRIANGLES,0,6);//drawtheclipspacequadsowegetoneresultforeachpixel Withthatdonewecanpulloutwhichtexturestousetocomputeclosestlines andtherestoftherenderingcodestaysthesame +const{linesTex,pointsTex}=newPointsLines; ...renderingcodefrompreviousexample... andfinallylikeourparticleexampleweswapoldandnew //swapoldandnewfornextframe { consttemp=oldPointsLines; oldPointsLines=newPointsLines; newPointsLines=temp; } requestAnimationFrame(render); } requestAnimationFrame(render); Andwiththatwecanseeitworkingdynamicallyandallthecomputation ishappeningontheGPU clickheretoopeninaseparatewindow SomeCaveatsaboutGPGPU GPGPUinWebGL1ismostlylimitedtousing2Darrays asoutputthoughyoucanoutputtomorethanone2Darray atthesametimeusingtheWEBGL_draw_buffersextension ifitexists. WebGL2addstheabilitytojustprocessa1Darrayofarbitrarysize. WebGPU(AFAIK)letsyouhaverandomaccesswriting,ie(computeshaders). GPUsdon'thavethesameprecisionasCPUs. Checkyourresultsandmakesuretheyareacceptable. ThereisoverheadtoGPGPU. Inthefirsttwoexamplesabovewecomputedsome datausingWebGLandthenreadtheresults.Settingupbuffers,textures settingattributesanduniformstakestime.Enoughtimethatforanything underacertainsizeitwouldbebettertojustdoitinJavaScript. Theactualexamplesmultiplying6numbersoradding3pairsofnumbers aremuchtoosmallforGPGPUtobeuseful.Wherethattradeoffis isundefined.Experimentbutjustaguessthatifyou'renotdoingatleast 1000ormorethingskeepitinJavaScript readPixelsisslow readingtheresultsfromWebGLisslowsoit'simportanttoavoidit asmuchaspossible.Asanexamplenethertheparticlesystemabovenor thedynamicclosestlinesexampleever readtheresultsbacktoJavaScript.Whereyoucan,keeptheresults ontheGPUforaslongaspossible.Inotherwords,youcoulddosomething like computestuffonGPU readresult prepresultfornextstep uploadpreppedresulttogpu computestuffonGPU readresult prepresultfornextstep uploadpreppedresulttogpu computestuffonGPU readresult whereasviacreativesolutionsitwouldbemuchfasterifyoucould computestuffonGPU prepresultfornextstepusingGPU computestuffonGPU prepresultfornextstepusingGPU computestuffonGPU readresult Ourdynamicclosestlinesexampledidthis.Theresultsneverleave theGPU. AsanotherexampleIoncewroteahistogramcomputingshader.Ithenread theresultsbackintoJavaScript,figuredouttheminandmaxvalues Thendrewtheimagebacktothecanvasusingthoseminandmaxvalues asuniformstoauto-leveltheimage. But,itturnedinsteadofreadingthehistogrambackintoJavaScript Icouldinsteadrunashaderonthehistogramitselfthatgenerated a2pixeltexturewiththeminandmaxvaluesinthetexture. Icouldthenpassthat2pixeltextureintothe3rdshaderwhichit couldreadfortheminandmaxvalues.Noneedtoreadthemoutofthe GPUforsettinguniforms. SimilarlytodisplaythehistogramitselfIfirstreadthehistogram datafromtheGPUbutlaterIinsteadwroteashaderthatcould visualizethehistogramdatadirectlyremovingtheneedtoreadit backtoJavaScript. BydoingthattheentireprocessstayedontheGPUandwaslikelymuch faster. GPUscandomanythingsinparallelbutmostcan'tmulti-taskthesameway aCPUcan.GPUsusuallycan'tdo"preemptivemultitasking". Thatmeansifyougivethemaverycomplexshaderthatsaytakes5minutesto runthey'llpotentiallyfreezeyourentiremachinefor5minutes. MostwellmadeOSesdealwiththisbyhavingtheCPUcheckhowlongit'sbeen sincethelastcommandtheygavetotheGPU.Ifit'sbeentolong(5-6second) andtheGPUhasnotrespondedthentheironlyoptionistoresettheGPU. ThisisonereasonwhyWebGLcanlosethecontextandyougetan"Aw,rats!" orsimilarmessage. It'seasytogivetheGPUtoomuchtodobutingraphicsit'snotthat commontotakeittothe5-6secondlevel.It'susuallymorelikethe0.1 secondlevelwhichisstillbadbutusuallyyouwantgraphicstorunfast andsotheprogrammerwillhopefullyoptimizeorfindadifferenttechnique tokeepthetheirappresponsive. GPGPUontheotherhandyoumighttrulywanttogivetheGPUaheavytask torun.Thereisnoeasysolutionhere.Amobilephonehasamuchlesspowerful GPUthanatopendPC.Otherthandoingyourowntimingthereisnowayto knowforsurehowmuchworkyoucangiveaGPUbeforeits"tooslow" Idon'thaveasolutiontooffer.Onlyawarningthatdependingonwhatyou're tryingtodoyoumayrunintothatissue. Mobiledevicesdon'tgenerallysupportrenderingtofloatingpointtextures Therearenoeasysolutionshere.Onesolutionisyoucantryto encodefloatingpointvaluesintoRGBA/UNSIGNED_BYTEvalues.Intheshader whenyoureadavaluefromthetextureyouneedtoconvertbackto floatingpointandwhenyououtputacoloryouneedtore-encodeit backintoRGBA/UNSIGNED_BYTE.Seethis But,forexample,ifweweretousethisintheparticleorclosestline examplesabovetheywouldrequiresignificantchanges.Thecodeabove isabletopulloutaposition(3values,x,y,z)withjustonelookup butnowwe'dneedtodo3lookups.Thecodeaboveisalsoabletowrite anew3valuepositiongl_FragColor=newPositionbutnowwe'donlybe abletowrite1value.We'deitherhavetotrytouseWEBGL_draw_buffers toletuswriteout3valuesto3differenttextures(yetmorework) orwe'dhavetoadjusttheshadertorun3times,onceforeachofX,Y,andZ Oneothersolutionissomemobiledevicessupportrenderingtohalffloats. Theproblemwithhalffloatsaretheyhaveverylittleprecisionsowhile theyareusefulforsomeproblemstheyaren'tnearlyasgenerallyuseful asnormal32bitfloatingpointvalues. IhopetheseexampleshelpedyouunderstandthekeyideaofGPGPUinWebGL isjustthefactthatWebGLreadsfromandwritesto2Dtextureswhichare really2DarraysofDATA,notjustpixelsforimages. Theyworksimilartomapfunctionsinthatthefunctionbeingcalled foreachvaluedoesn'tgettodecidewhereitsvaluewillbestored. Ratherthatisdecidedfromtheoutsidethefunction.InWebGL'scase that'sdecidedbyhowyousetupwhatyou'redrawing.Onceyoucallgl.drawXXX theshaderwillbecalledforeachneededvaluebeingasked"whatvalueshould Imakethis?" Andthat'sreallyit. Theexamplesabovemostlyused2Dtexturesas1Darraysbutofcourse youcanusethemas2Darrays(forexamplemultiplying2largematrices formachinelearning),orsimilarlytohowwedidmathtotreat2Darrays as1Darrayswecouldalsowritemathtotreat2Darraysas3Darrays andusethatforthingslikefluidsimulations. SincewemadesomeparticlesviaGPGPUthereisthiswonderfulvideowhichinitssecondhalf usescomputeshaderstodoa"slime"simulation. UsingthetechniquesabovehereitistranslatedintoWebGL. English Français 日本語 한국어 Polski Portuguese Русский 简体中文 Fundamentals Fundamentals HowItWorks ShadersandGLSL WebGLStateDiagram ImageProcessing ImageProcessing ImageProcessingContinued 2Dtranslation,rotation,scale,matrixmath 2DTranslation 2DRotation 2DScale 2DMatrices 3D Orthographic3D 3DPerspective 3DCameras Lighting DirectionalLighting PointLighting SpotLighting StructureandOrganization LessCode,MoreFun DrawingMultipleThings SceneGraphs Geometry Geometry-Lathe Loading.objfiles Loading.objw.mtlfiles Textures Textures DataTextures Using2orMoreTextures CrossOriginImages PerspectiveCorrectTextureMapping PlanarandPerspectiveProjectionMapping RenderingToATexture RendertoTexture Shadows Shadows Techniques 2D 2D-DrawImage 2D-MatrixStack Sprites 3D Cubemaps Environmentmaps Skyboxes Skinning Fog Picking(clickingonstuff) Text Text-HTML Text-Canvas2D Text-UsingaTexture Text-UsingaGlyphTexture Textures RampTextures(ToonShading) GPGPU GPGPU Tips SmallestPrograms DrawingWithoutData Shadertoy PullingVertices Optimization IndexedVertices(gl.drawElements) InstancedDrawing Misc SetupAndInstallation Boilerplate ResizingtheCanvas Animation Points,Lines,andTriangles MultipleViews,MultipleCanvases VisualizingtheCamera WebGLandAlpha 2Dvs3Dlibraries Anti-Patterns WebGLMatricesvsMathMatrices PrecisionIssues Takingascreenshot PreventtheCanvasBeingCleared GetKeyboardInputFromaCanvas UseWebGLasBackgroundinHTML CrossPlatformIssues QuestionsandAnswers Reference Attributes TextureUnits Framebuffers readPixels References HelperAPIDocs TWGL,AtinyWebGLhelperlibrary github Questions?Askonstackoverflow. Issue/Bug?Createanissueongithub. Use

codegoeshere
forcodeblocks commentspoweredbyDisqus



請為這篇文章評分?