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延伸文章資訊
- 1Image Processing with WebGL - Medium
Image processing with HTML Canvas. Before delving into WebGL rendering, I think it's worth briefl...
- 2Drawing an image using WebGL - html5 canvas - Stack Overflow
2D Image Processing With WebGL - javascript - Stack Overflow
- 3WebGL Image Processing: Live Code Session - Supercharged
- 4WebGL tutorial: image processing - posts in a row / Habr
WebGL is a web standard for low-level 3D graphics API. It allows you to run your code directly on...
- 5WebGL Image Processing
To draw images in WebGL we need to use textures. Similarly to the way WebGL expects clip space co...