WebGL How It Works

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

Buffers are the way of getting vertex and other per vertex data onto the GPU. gl.createBuffer creates a buffer. gl.bindBuffer sets that buffer as the buffer ... English Français 日本語 한국어 Polski Portuguese Русский 简体中文 TableofContents WebGLFundamentals.org Fix,Fork,Contribute WebGLHowItWorks ThisisacontinuationfromWebGLFundamentals. BeforewecontinueIthinkweneedtodiscussata basiclevelwhatWebGLandyourGPUactuallydo.Therearebasically2 partstothisGPUthing.Thefirstpartprocessesvertices(orstreamsof data)intoclipspacevertices.Thesecondpartdrawspixelsbasedonthe firstpart. Whenyoucall varprimitiveType=gl.TRIANGLES; varoffset=0; varcount=9; gl.drawArrays(primitiveType,offset,count); The9theremeans"process9vertices"sohereare9verticesbeingprocessed. Ontheleftisthedatayouprovide.Thevertexshaderisafunctionyou writeinGLSL.Itgetscalledonceforeachvertex. Youdosomemathandsetthespecialvariablegl_Positionwithaclipspacevalue forthecurrentvertex.TheGPUtakesthatvalueandstoresitinternally. Assumingyou'redrawingTRIANGLES,everytimethisfirstpartgenerates3 verticestheGPUusesthemtomakeatriangle.Itfiguresoutwhich pixelsthe3pointsofthetrianglecorrespondto,andthenrasterizesthe trianglewhichisafancywordfor“drawsitwithpixels”.Foreach pixelitwillcallyourfragmentshaderaskingyouwhatcolortomakethat pixel.Yourfragmentshaderhastosetaspecialvariablegl_FragColor withthecoloritwantsforthatpixel. That’sallveryinterestingbutasyoucanseeinourexamplesupto thispointthefragmentshaderhasverylittleinfoperpixel. Fortunatelywecanpassitmoreinfo.Wedefine“varyings”foreach valuewewanttopassfromthevertexshadertothefragmentshader. Asasimpleexample,let'sjustpasstheclipspacecoordinateswecomputed directlyfromthevertexshadertothefragmentshader. We'lldrawwithasimpletriangle.Continuingfromour previousexamplelet'schangeourrectangletoa triangle. //Fillthebufferwiththevaluesthatdefineatriangle. functionsetGeometry(gl){ gl.bufferData( gl.ARRAY_BUFFER, newFloat32Array([ 0,-100, 150,125, -175,100]), gl.STATIC_DRAW); } Andwehavetoonlydraw3vertices. //Drawthescene. functiondrawScene(){ ... //Drawthegeometry. varprimitiveType=gl.TRIANGLES; varoffset=0; varcount=3; gl.drawArrays(primitiveType,offset,count); } Theninourvertexshaderwedeclareavaryingtopassdatatothe fragmentshader. *varyingvec4v_color; ... voidmain(){ //Multiplythepositionbythematrix. gl_Position=vec4((u_matrix*vec3(a_position,1)).xy,0,1); //Convertfromclipspacetocolorspace. //Clipspacegoes-1.0to+1.0 //Colorspacegoesfrom0.0to1.0 *v_color=gl_Position*0.5+0.5; } Andthenwedeclarethesamevaryinginthefragmentshader. precisionmediumpfloat; *varyingvec4v_color; voidmain(){ *gl_FragColor=v_color; } WebGLwillconnectthevaryinginthevertexshadertothevaryingofthe samenameandtypeinthefragmentshader. Here'stheworkingversion. clickheretoopeninaseparatewindow Move,scaleandrotatethetriangle.Noticethatsincethecolorsare computedfromclipspacetheydon'tmovewiththetriangle.Theyare relativetothebackground. Nowthinkaboutit.Weonlycompute3vertices.Ourvertexshaderonly getscalled3timesthereforeit'sonlycomputing3colorsyetour triangleismanycolors.Thisiswhyit'scalledavarying. WebGLtakesthe3valueswecomputedforeachvertexandasitrasterizes thetriangleitinterpolatesbetweenthevalueswecomputedforthe vertices.Foreachpixelitcallsourfragmentshaderwiththe interpolatedvalueforthatpixel. Intheexampleabovewestartoutwiththe3vertices Vertices 0-100 150125 -175100 Ourvertexshaderappliesamatrixtotranslate,rotate,scaleandconvert toclipspace.Thedefaultsfortranslation,rotationandscaleare translation=200,150,rotation=0,scale=1,1sothat'sreallyonly translation.Givenourbackbufferis400x300ourvertexshaderapplies thematrixandthencomputesthefollowing3clipspacevertices. valueswrittentogl_Position 0.0000.660 0.750-0.830 -0.875-0.660 Italsoconvertsthosetocolorspaceandwritesthemtothevarying v_colorthatwedeclared. valueswrittentov_color 0.50000.8300.5 0.87500.0860.5 0.06250.1700.5 Those3valueswrittentov_coloraretheninterpolatedandpassedtothe fragmentshaderforeachpixel. v_colorisinterpolatedbetweenv0,v1andv2 Wecanalsopassinmoredatatothevertexshaderwhichwecanthenpass ontothefragmentshader.Soforexamplelet'sdrawarectangle,that consistsof2triangles,in2colors.Todothiswe'lladdanother attributetothevertexshadersowecanpassitmoredataandwe'llpass thatdatadirectlytothefragmentshader. attributevec2a_position; +attributevec4a_color; ... varyingvec4v_color; voidmain(){ ... //Copythecolorfromtheattributetothevarying. *v_color=a_color; } WenowhavetosupplycolorsforWebGLtouse. //lookupwherethevertexdataneedstogo. varpositionLocation=gl.getAttribLocation(program,"a_position"); +varcolorLocation=gl.getAttribLocation(program,"a_color"); ... +//Createabufferforthecolors. +varcolorBuffer=gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer); +//Setthecolors. +setColors(gl); ... +//Fillthebufferwithcolorsforthe2triangles +//thatmaketherectangle. +functionsetColors(gl){ +//Pick2randomcolors. +varr1=Math.random(); +varb1=Math.random(); +varg1=Math.random(); + +varr2=Math.random(); +varb2=Math.random(); +varg2=Math.random(); + +gl.bufferData( +gl.ARRAY_BUFFER, +newFloat32Array( +[r1,b1,g1,1, +r1,b1,g1,1, +r1,b1,g1,1, +r2,b2,g2,1, +r2,b2,g2,1, +r2,b2,g2,1]), +gl.STATIC_DRAW); +} Atrendertimesetupthecolorattribute +gl.enableVertexAttribArray(colorLocation); + +//Bindthecolorbuffer. +gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer); + +//TellthecolorattributehowtogetdataoutofcolorBuffer(ARRAY_BUFFER) +varsize=4;//4componentsperiteration +vartype=gl.FLOAT;//thedatais32bitfloats +varnormalize=false;//don'tnormalizethedata +varstride=0;//0=moveforwardsize*sizeof(type)eachiterationtogetthenextposition +varoffset=0;//startatthebeginningofthebuffer +gl.vertexAttribPointer( +colorLocation,size,type,normalize,stride,offset) Andadjustthecounttocompute6verticesfor2triangles //Drawthegeometry. varprimitiveType=gl.TRIANGLES; varoffset=0; *varcount=6; gl.drawArrays(primitiveType,offset,count); Andhere'stheresult. clickheretoopeninaseparatewindow Noticethatwehave2solidcolortriangles.Yetwe'repassingthevalues inavaryingsotheyarebeingvariedorinterpolatedacrossthe triangle.It'sjustthatweusedthesamecoloroneachofthe3vertices ofeachtriangle.Ifwemakeeachcolordifferentwe'llseethe interpolation. //Fillthebufferwithcolorsforthe2triangles //thatmaketherectangle. functionsetColors(gl){ //Makeeveryvertexadifferentcolor. gl.bufferData( gl.ARRAY_BUFFER, newFloat32Array( *[Math.random(),Math.random(),Math.random(),1, *Math.random(),Math.random(),Math.random(),1, *Math.random(),Math.random(),Math.random(),1, *Math.random(),Math.random(),Math.random(),1, *Math.random(),Math.random(),Math.random(),1, *Math.random(),Math.random(),Math.random(),1]), gl.STATIC_DRAW); } Andnowweseetheinterpolatedvarying. clickheretoopeninaseparatewindow NotveryexcitingIsupposebutitdoesdemonstrateusingmorethanone attributeandpassingdatafromavertexshadertoafragmentshader.If youcheckouttheimageprocessingexamples you'llseetheyalsouseanextraattributetopassintexturecoordinates. Whatdothesebufferandattributecommandsdo? Buffersarethewayofgettingvertexandotherpervertexdataontothe GPU.gl.createBuffercreatesabuffer. gl.bindBuffersetsthatbufferasthebuffertobeworkedon. gl.bufferDatacopiesdataintothebuffer.Thisisusuallydoneat initializationtime. OncethedataisinthebufferweneedtotellWebGLhowtogetdataout ofitandprovideittothevertexshader'sattributes. Todothis,firstweaskWebGLwhatlocationsitassignedtothe attributes.Forexampleinthecodeabovewehave //lookupwherethevertexdataneedstogo. varpositionLocation=gl.getAttribLocation(program,"a_position"); varcolorLocation=gl.getAttribLocation(program,"a_color"); Thisisalsousuallydoneatinitializationtime. Onceweknowthelocationoftheattributewethenissue3commandsjust beforedrawing. gl.enableVertexAttribArray(location); ThatcommandtellsWebGLwewanttosupplydatafromabuffer. gl.bindBuffer(gl.ARRAY_BUFFER,someBuffer); ThatcommandbindsabuffertotheARRAY_BUFFERbindpoint.It'saglobal variableinternaltoWebGL gl.vertexAttribPointer( location, numComponents, typeOfData, normalizeFlag, strideToNextPieceOfData, offsetIntoBuffer); AndthatcommandtellsWebGLtogetdatafromthebufferthatiscurrently boundtotheARRAY_BUFFERbindpoint,howmanycomponentspervertex(1-4), whatthetypeofdatais(BYTE,FLOAT,INT,UNSIGNED_SHORT,etc...), thestridewhichmeanshowmanybytestoskiptogetfromonepieceofdatatothe nextpieceofdata,andanoffsetforhowfarintothebufferourdatais. Numberofcomponentsisalways1to4. Ifyouareusing1bufferpertypeofdatathenbothstrideandoffsetcan alwaysbe0.0forstridemeans"useastridethatmatchesthetypeand size".0foroffsetmeansstartatthebeginningofthebuffer.Setting themtovaluesotherthan0ismorecomplicatedandthoughithassome benefitsintermsofperformanceit'snotworththecomplicationunless youaretryingtopushWebGLtoitsabsolutelimits. Ihopethatclearsupbuffersandattributes. Youmightwanttotakealookatthis interactivestatediagram foranotherwayofunderstandinghowWebGLworks. Nextlet'sgoovershadersandGLSL. What'snormalizeFlagforinvertexAttribPointer? Thenormalizeflagisforallthenonfloatingpointtypes.Ifyoupass infalsethenvalueswillbeinterpretedasthetypetheyare.BYTEgoes from-128to127,UNSIGNED_BYTEgoesfrom0to255,SHORTgoesfrom-32768to32767etc... IfyousetthenormalizeflagtotruethenthevaluesofaBYTE(-128to127) representthevalues-1.0to+1.0,UNSIGNED_BYTE(0to255)become0.0to+1.0. AnormalizedSHORTalsogoesfrom-1.0to+1.0itjusthasmoreresolutionthanaBYTE. Themostcommonusefornormalizeddataisforcolors.Mostofthetimecolors onlygofrom0.0to1.0.Usingafullfloateachforred,green,blueandalpha woulduse16bytespervertexpercolor.Ifyouhavecomplicatedgeometrythat canadduptoalotofbytes.InsteadyoucouldconvertyourcolorstoUNSIGNED_BYTEs where0represents0.0and255represents1.0.Nowyou'donlyneed4bytespercolor pervertex,a75%savings. Let'schangeourcodetodothis.WhenwetellWebGLhowtoextractourcolorswe'duse //TellthecolorattributehowtogetdataoutofcolorBuffer(ARRAY_BUFFER) varsize=4;//4componentsperiteration *vartype=gl.UNSIGNED_BYTE;//thedatais8bitunsignedbytes *varnormalize=true;//normalizethedata varstride=0;//0=moveforwardsize*sizeof(type)eachiterationtogetthenextposition varoffset=0;//startatthebeginningofthebuffer gl.vertexAttribPointer( colorLocation,size,type,normalize,stride,offset) Andwhenwefilloutourbufferwithcolorswe'duse //Fillthebufferwithcolorsforthe2triangles //thatmaketherectangle. functionsetColors(gl){ //Pick2randomcolors. varr1=Math.random()*256;//0to255.99999 varb1=Math.random()*256;//thesevalues varg1=Math.random()*256;//willbetruncated varr2=Math.random()*256;//whenstoredinthe varb2=Math.random()*256;//Uint8Array varg2=Math.random()*256; gl.bufferData( gl.ARRAY_BUFFER, newUint8Array(//Uint8Array [r1,b1,g1,255, r1,b1,g1,255, r1,b1,g1,255, r2,b2,g2,255, r2,b2,g2,255, r2,b2,g2,255]), gl.STATIC_DRAW); } Here'sthatsample. clickheretoopeninaseparatewindow 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


請為這篇文章評分?