Using textures in WebGL - Web APIs | MDN - Mozilla

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

The textureCoordinates array defines the texture coordinates corresponding to each vertex of each face. Note that the texture coordinates range ... 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. Note:CORSsupportforWebGLtexturesandthecrossOriginattributeforimageelementsisimplementedinGecko 8.0. Tainted(write-only)2Dcanvasescan'tbeusedasWebGLtextures.A2Dbecomestainted,forexample,whenacross-domainimageisdrawnonit. Note:CORSsupportforCanvas2DdrawImageisimplementedinGecko 9.0.Thismeansthatusingacross-domainimagewithCORSapprovaldoesnolongertaintthe2Dcanvas,sothe2DcanvasremainsusableasthesourceofaWebGLtexture. Note:CORSsupportforcross-domainvideosandthecrossoriginattributefor


請為這篇文章評分?