Using textures in WebGL - Web APIs | MDN

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

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.A2Dbecomestainted,forexample,whenacross-domainimageisdrawnonit. Note:CORSsupportforCanvas2DdrawImageisimplementedinGecko 9.0.Thismeansthatusingacross-domainimagewithCORSapprovaldoesnolongertaintthe2Dcanvas,sothe2DcanvasremainsusableasthesourceofaWebGLtexture. Note:CORSsupportforcross-domainvideosandthecrossoriginattributefor


請為這篇文章評分?