Using textures in WebGL - Web APIs | MDN
文章推薦指數: 80 %
To load the texture from the image file, it then creates an Image object and assigns the src to the URL for our image we wish to use as our ... SkiptomaincontentSkiptosearchSkiptoselectlanguageReferencesWebAPIsWebGL:2Dand3DgraphicsforthewebWebGLtutorialUsingtexturesinWebGLArticleActionsEnglish(US)LoadingtexturesMappingthetextureontothefacesUpdatingtheshadersDrawingthetexturedcubeCross-domaintexturesRelatedTopics WebGLAPI WebGLtutorial GettingstartedwithWebGL Adding2DcontenttoaWebGLcontext UsingshaderstoapplycolorinWebGL AnimatingobjectswithWebGL Creating3DobjectsusingWebGL UsingtexturesinWebGL LightinginWebGL AnimatingtexturesinWebGL Examplesandarticles Matrixmathfortheweb WebGLmodelviewprojection WebGLbestpractices UsingWebGLextensions Abasic2DWebGLanimationexample WebGLbyexample Interfaces WebGLRenderingContext WebGL2RenderingContext WebGLActiveInfo WebGLBuffer WebGLContextEvent WebGLFramebuffer WebGLProgram WebGLQuery WebGLRenderbuffer WebGLSampler WebGLShader WebGLShaderPrecisionFormat WebGLSync WebGLTexture WebGLTransformFeedback WebGLUniformLocation WebGLVertexArrayObject Documentation: Contribute TheMDNproject LoadingtexturesMappingthetextureontothefacesUpdatingtheshadersDrawingthetexturedcubeCross-domaintexturesUsingtexturesinWebGL «Previous Next» Nowthatoursampleprogramhasarotating3Dcube,let'smapatextureontoitinsteadofhavingitsfacesbesolidcolors. Note:ThisexampleusestheglMatrixlibrarytoperformitsmatrixandvertexmath.You'llneedtoincludeitifyoucreateyourownprojectbasedonthiscode.OursampleloadsacopyfromaCDNinourHTML's
. LoadingtexturesThefirstthingtodoisaddcodetoloadthetextures.Inourcase,we'llbeusingasingletexture,mappedontoallsixsidesofourrotatingcube,butthesametechniquecanbeusedforanynumberoftextures. Note:It'simportanttonotethattheloadingoftexturesfollowscross-domainrules;thatis,youcanonlyloadtexturesfromsitesforwhichyourcontenthasCORSapproval.SeeCross-domaintexturesbelowfordetails. Thecodethatloadsthetexturelookslikethis: // //Initializeatextureandloadanimage. //Whentheimagefinishedloadingcopyitintothetexture. // functionloadTexture(gl,url){ consttexture=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,texture); //Becauseimageshavetobedownloadedovertheinternet //theymighttakeamomentuntiltheyareready. //Untilthenputasinglepixelinthetexturesowecan //useitimmediately.Whentheimagehasfinisheddownloading //we'llupdatethetexturewiththecontentsoftheimage. constlevel=0; constinternalFormat=gl.RGBA; constwidth=1; constheight=1; constborder=0; constsrcFormat=gl.RGBA; constsrcType=gl.UNSIGNED_BYTE; constpixel=newUint8Array([0,0,255,255]);//opaqueblue gl.texImage2D(gl.TEXTURE_2D,level,internalFormat, width,height,border,srcFormat,srcType, pixel); constimage=newImage(); image.onload=function(){ gl.bindTexture(gl.TEXTURE_2D,texture); gl.texImage2D(gl.TEXTURE_2D,level,internalFormat, srcFormat,srcType,image); //WebGL1hasdifferentrequirementsforpowerof2images //vsnonpowerof2imagessocheckiftheimageisa //powerof2inbothdimensions. if(isPowerOf2(image.width)&&isPowerOf2(image.height)){ //Yes,it'sapowerof2.Generatemips. gl.generateMipmap(gl.TEXTURE_2D); }else{ //No,it'snotapowerof2.Turnoffmipsandset //wrappingtoclamptoedge 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); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); } }; image.src=url; returntexture; } functionisPowerOf2(value){ return(value&(value-1))==0; } TheloadTexture()routinestartsbycreatingaWebGLtextureobjecttexturebycallingtheWebGLcreateTexture()function.ItthenuploadsasinglebluepixelusingtexImage2D().Thismakesthetextureimmediatelyusableasasolidbluecoloreventhoughitmaytakeafewmomentsforourimagetodownload. Toloadthetexturefromtheimagefile,itthencreatesanImageobjectandassignsthesrctotheURLforourimagewewishtouseasourtexture.Thefunctionweassigntoimage.onloadwillbecalledoncetheimagehasfinisheddownloading.AtthatpointweagaincalltexImage2D()thistimeusingtheimageasthesourceforthetexture.Afterthatwesetupfilteringandwrappingforthetexturebasedonwhetherornottheimagewedownloadwasapowerof2inbothdimensionsornot. WebGL1canonlyusenonpowerof2textureswithfilteringsettoNEARESTorLINEARanditcannotgenerateamipmapforthem.TheirwrappingmodemustalsobesettoCLAMP_TO_EDGE.Ontheotherhandifthetextureisapowerof2inbothdimensionsthenWebGLcandohigherqualityfiltering,itcanusemipmap,anditcansetthewrappingmodetoREPEATorMIRRORED_REPEAT. Anexampleofarepeatedtextureistilinganimageofafewbrickstocoverabrickwall. MipmappingandUVrepeatingcanbedisabledwithtexParameteri().Thiswillallownon-power-of-two(NPOT)texturesattheexpenseofmipmapping,UVwrapping,UVtiling,andyourcontroloverhowthedevicewillhandleyourtexture. //gl.NEARESTisalsoallowed,insteadofgl.LINEAR,asneithermipmap. gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR); //Preventss-coordinatewrapping(repeating). gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE); //Preventst-coordinatewrapping(repeating). gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE); Again,withtheseparameters,compatibleWebGLdeviceswillautomaticallyacceptanyresolutionforthattexture(uptotheirmaximumdimensions).Withoutperformingtheaboveconfiguration,WebGLrequiresallsamplesofNPOTtexturestofailbyreturningtransparentblack:rgba(0,0,0,0). Toloadtheimage,addacalltoourloadTexture()functionwithinourmain()function.ThiscanbeaddedaftertheinitBuffers(gl)call. //Loadtexture consttexture=loadTexture(gl,'cubetexture.png'); MappingthetextureontothefacesAtthispoint,thetextureisloadedandreadytouse.Butbeforewecanuseit,weneedtoestablishthemappingofthetexturecoordinatestotheverticesofthefacesofourcube.Thisreplacesallthepreviouslyexistingcodeforconfiguringcolorsforeachofthecube'sfacesininitBuffers(). consttextureCoordBuffer=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,textureCoordBuffer); consttextureCoordinates=[ //Front 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, //Back 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, //Top 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, //Bottom 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, //Right 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, //Left 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, ]; gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(textureCoordinates), gl.STATIC_DRAW); ... return{ position:positionBuffer, textureCoord:textureCoordBuffer, indices:indexBuffer, }; First,thiscodecreatesaWebGLbufferintowhichwe'llstorethetexturecoordinatesforeachface,thenwebindthatbufferasthearraywe'llbewritinginto. ThetextureCoordinatesarraydefinesthetexturecoordinatescorrespondingtoeachvertexofeachface.Notethatthetexturecoordinatesrangefrom0.0to1.0;thedimensionsoftexturesarenormalizedtoarangeof0.0to1.0regardlessoftheiractualsize,forthepurposeoftexturemapping. Oncewe'vesetupthetexturemappingarray,wepassthearrayintothebuffer,sothatWebGLhasthatdatareadyforitsuse.UpdatingtheshadersTheshaderprogramalsoneedstobeupdatedtousethetexturesinsteadofsolidcolors.ThevertexshaderWeneedtoreplacethevertexshadersothatinsteadoffetchingcolordata,itinsteadfetchesthetexturecoordinatedata. constvsSource=` attributevec4aVertexPosition; attributevec2aTextureCoord; uniformmat4uModelViewMatrix; uniformmat4uProjectionMatrix; varyinghighpvec2vTextureCoord; voidmain(void){ gl_Position=uProjectionMatrix*uModelViewMatrix*aVertexPosition; vTextureCoord=aTextureCoord; } `; Thekeychangehereisthatinsteadoffetchingthevertexcolor,we'refetchingthetexturecoordinatesandpassingthemtothevertexshader;thiswillindicatethelocationwithinthetexturecorrespondingtothevertex.ThefragmentshaderThefragmentshaderlikewiseneedstobeupdated: constfsSource=` varyinghighpvec2vTextureCoord; uniformsampler2DuSampler; voidmain(void){ gl_FragColor=texture2D(uSampler,vTextureCoord); } `; Insteadofassigningacolorvaluetothefragment'scolor,thefragment'scoloriscomputedbyfetchingthetexel(thatis,thepixelwithinthetexture)basedonthevalueofvTextureCoordwhichlikethecolorsisinterpolatedbetweenvertices.AttributeandUniformLocationsBecausewechangedanattributeandaddedauniformweneedtolookuptheirlocations constprogramInfo={ program:shaderProgram, attribLocations:{ vertexPosition:gl.getAttribLocation(shaderProgram,'aVertexPosition'), textureCoord:gl.getAttribLocation(shaderProgram,'aTextureCoord'), }, uniformLocations:{ projectionMatrix:gl.getUniformLocation(shaderProgram,'uProjectionMatrix'), modelViewMatrix:gl.getUniformLocation(shaderProgram,'uModelViewMatrix'), uSampler:gl.getUniformLocation(shaderProgram,'uSampler'), }, }; DrawingthetexturedcubeThechangestothedrawScene()functionaresimple. First,thecodetospecifythecolorsbufferisgone,replacedwiththis: //tellwebglhowtopulloutthetexturecoordinatesfrombuffer { constnum=2;//everycoordinatecomposedof2values consttype=gl.FLOAT;//thedatainthebufferis32-bitfloat constnormalize=false;//don'tnormalize conststride=0;//howmanybytestogetfromonesettothenext constoffset=0;//howmanybytesinsidethebuffertostartfrom gl.bindBuffer(gl.ARRAY_BUFFER,buffers.textureCoord); gl.vertexAttribPointer(programInfo.attribLocations.textureCoord,num,type,normalize,stride,offset); gl.enableVertexAttribArray(programInfo.attribLocations.textureCoord); } Thenaddcodetospecifythetexturetomapontothefaces,justbeforedraw: //TellWebGLwewanttoaffecttextureunit0 gl.activeTexture(gl.TEXTURE0); //Bindthetexturetotextureunit0 gl.bindTexture(gl.TEXTURE_2D,texture); //Telltheshaderweboundthetexturetotextureunit0 gl.uniform1i(programInfo.uniformLocations.uSampler,0); WebGLprovidesaminimumof8textureunits;thefirstoftheseisgl.TEXTURE0.WetellWebGLwewanttoaffectunit0.WethencallbindTexture()whichbindsthetexturetotheTEXTURE_2Dbindpointoftextureunit0.WethentelltheshaderthatfortheuSamplerusetextureunit0. Lastly,addtextureasaparametertothedrawScene()function,bothwhereitisdefinedandwhereitiscalled. drawScene(gl,programInfo,buffers,texture,deltaTime); ... functiondrawScene(gl,programInfo,buffers,texture,deltaTime){ Atthispoint,therotatingcubeshouldbegoodtogo. Viewthecompletecode|OpenthisdemoonanewpageCross-domaintexturesLoadingofWebGLtexturesissubjecttocross-domainaccesscontrols.Inorderforyourcontenttoloadatexturefromanotherdomain,CORSapprovalneedstobeobtained.SeeHTTPaccesscontrolfordetailsonCORS. BecauseWebGLnowrequirestexturestobeloadedfromsecurecontexts,youcan'tusetexturesloadedfromfile:///URLsinWebGL.Thatmeansthatyou'llneedasecurewebservertotestanddeployyourcode.Forlocaltesting,seeourguideHowdoyousetupalocaltestingserver?forhelp. Seethishacks.mozilla.orgarticleforanexplanationofhowtouseCORS-approvedimagesasWebGLtextures,withaself-containedexample. Note:CORSsupportforWebGLtexturesandthecrossOriginattributeforimageelementsisimplementedinGecko 8.0. Tainted(write-only)2Dcanvasescan'tbeusedasWebGLtextures.A2D延伸文章資訊
- 1WebGL2 Image Processing
To draw images in WebGL we need to use textures. Similarly to the way WebGL expects clip space co...
- 2WebGL Image Processing: Live Code Session - Supercharged
- 3jongomez/numgl: Image processing with WebGL. - GitHub
Apply image processing algorithms using WebGL. Supports pictures, videos, webcam streams and user...
- 4Drawing an image using WebGL - html5 canvas - Stack Overflow
2D Image Processing With WebGL - javascript - Stack Overflow
- 5Image Processing with WebGL - Medium
Image processing with HTML Canvas. Before delving into WebGL rendering, I think it's worth briefl...