Using textures in WebGL - Web APIs | MDN - Mozilla
文章推薦指數: 80 %
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.A2D延伸文章資訊
- 1WebGL基础学习篇(Lesson 7)
What is texture mapping. 纹理从字面上理解就是使用图片渲染在物体的表面上。正如下面的图所示:. 使用目前我们已 ...
- 2Using textures in WebGL - Web APIs | MDN - Mozilla
The textureCoordinates array defines the texture coordinates corresponding to each vertex of each...
- 3How to use data textures in WebGL - Stack Overflow
Addressing individual pixels in a texture in WebGL1 uses this formula vec2 pixelCoord = vec2(x, y...
- 4Texture2D.CreateExternalTexture from a webgl texture
I'm creating a webgl texture in javascript, and trying to get back the handle pointer for the tex...
- 5texture2D - The Book of Shaders
The texture2D function returns a texel, i.e. the (color) value of the texture for the given coord...