首页 > 编程 > HTML > 正文

在支持HTML5的浏览器上运行WebGL程序的方法

2020-03-24 16:04:11
字体:
来源:转载
供稿:网友
前提条件和预期结果目前只有少数的浏览器支持 WebGL ,请看我的另外一篇文章:Can I use WebGL?.下面的例子是在 Windows 下的 Chrome 16/23 以及 Android 下的 Firefox 17 进行测试。如果你使用的是非兼容浏览器访问则会弹出一个警告。
图1:包含 Hello world 文本的动画的 WebGL 立方体
在兼容 HTML5 的浏览器上,你将会看到如下图所示的带动画效果的立方体:
图2: 示例运行的屏幕截图
该代码基于 Lighting in WebGL - How to simulate lighting effects in your WebGL context - 非常感谢这篇教程。在该实例初始运行时,动画的立方体是通过一个静态的 Bitmap 图形对象渲染的。下面的代码演示如何在程序中动态的渲染文本:XML/HTML Code复制内容到剪贴板
//TODO#1Newmethodtocreateatexture functioncreateCubeTexture(text){ ... }
在这里使用 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 是非常重要的,用来确保写文本时不会前后颠倒。剩下的就很容易理解了:XML/HTML Code复制内容到剪贴板
//TODO#2Assignthecreatedtexturefordisplay cubeTexture=createCubeTexture( HelloWorld!
title WebGL-HelloWorld! /title metahttp-equiv= Content-Type content= text/html;charset=utf-8 scriptsrc= sylvester.js type= text/javascript /script scriptsrc= glUtils.js type= text/javascript /script scriptsrc= webgl-demo.js type= text/javascript /script !--Fragmentshaderprogram-- scriptid= shader-fs type= x-shader/x-fragment varyinghighpvec2vTextureCoord; varyinghighpvec3vLighting; uniformsampler2DuSampler; voidmain(void){ highpvec4texelColor=texture2D(uSampler,vec2(vTextureCoord.s,vTextureCoord.t)); gl_FragColor=vec4(texelColor.rgb*vLighting,texelColor.a); } /script !--Vertexshaderprogram-- scriptid= shader-vs type= x-shader/x-vertex attributehighpvec3aVertexNormal; attributehighpvec3aVertexPosition; attributehighpvec2aTextureCoord; uniformhighpmat4uNormalMatrix; uniformhighpmat4uMVMatrix; uniformhighpmat4uPMatrix; varyinghighpvec2vTextureCoord; varyinghighpvec3vLighting; voidmain(void){ gl_Position=uPMatrix*uMVMatrix*vec4(aVertexPosition,1.0); vTextureCoord=aTextureCoord; //Applylightingeffect highpvec3ambientLight=vec3(0.6,0.6,0.6); highpvec3directionalLightColor=vec3(0.5,0.5,0.75); highpvec3directionalVector=vec3(0.85,0.8,0.75); highpvec4transformedNormal=uNormalMatrix*vec4(aVertexNormal,1.0); highpfloatdirectional=max(dot(transformedNormal.xyz,directionalVector),0.0); vLighting=ambientLight+(directionalLightColor*directional); } /script /head bodyonload= start() canvasid= glcanvas width= 640 height= 480 Yourbrowserdoesn'tappeartosupporttheHTML5 code canvas /code element. /canvas /body /html
varcubeVerticesTextureCoordBuffer; varcubeVerticesIndexBuffer; varcubeVerticesIndexBuffer; varcubeRotation=0.0; varlastCubeUpdateTime=0; varcubeImage; varcubeTexture; varmvMatrix; varshaderProgram; varvertexPositionAttribute; varvertexNormalAttribute; vartextureCoordAttribute; varperspectiveMatrix; // //start // //Calledwhenthecanvasiscreatedtogettheballrolling. // functionstart(){ canvas=document.getElementById( glcanvas initWebGL(canvas);//InitializetheGLcontext //OnlycontinueifWebGLisavailableandworking if(gl){ gl.clearColor(0.0,0.0,0.0,1.0);//Cleartoblack,fullyopaque gl.clearDepth(1.0);//Cleareverything gl.enable(gl.DEPTH_TEST);//Enabledepthtesting gl.depthFunc(gl.LEQUAL);//Nearthingsobscurefarthings //Initializetheshaders;thisiswhereallthelightingforthe //verticesandsoforthisestablished. initShaders(); //Here'swherewecalltheroutinethatbuildsalltheobjects //we'llbedrawing. initBuffers(); //Next,loadandsetupthetextureswe'llbeusing. //TODO#2Start cubeTexture=createCubeTexture( HelloWorld! //TODO#2End //Setuptodrawthesceneperiodically. setInterval(drawScene,15); } } // //initWebGL // //InitializeWebGL,returningtheGLcontextornullif //WebGLisn'tavailableorcouldnotbeinitialized. // functioninitWebGL(){ gl=null; try{ gl=canvas.getContext( experimental-webgl } catch(e){ } //Ifwedon'thaveaGLcontext,giveupnow if(!gl){ alert( UnabletoinitializeWebGL.Yourbrowsermaynotsupportit. } } // //initBuffers // //Initializethebufferswe'llneed.Forthisdemo,wejusthave //oneobject--asimpletwo-dimensionalcube. // functioninitBuffers(){ //Createabufferforthecube'svertices. cubeVerticesBuffer=gl.createBuffer(); //SelectthecubeVerticesBufferastheonetoapplyvertex //operationstofromhereout. gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesBuffer); //Nowcreateanarrayofverticesforthecube. varvertices=[ //Frontface -1.0,-1.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0, //Backface -1.0,-1.0,-1.0, -1.0,1.0,-1.0, 1.0,1.0,-1.0, 1.0,-1.0,-1.0, //Topface -1.0,1.0,-1.0, -1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,-1.0, //Bottomface -1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0,1.0, -1.0,-1.0,1.0, //Rightface 1.0,-1.0,-1.0, 1.0,1.0,-1.0, 1.0,1.0,1.0, 1.0,-1.0,1.0, //Leftface -1.0,-1.0,-1.0, -1.0,-1.0,1.0, -1.0,1.0,1.0, -1.0,1.0,-1.0 ]; //NowpassthelistofverticesintoWebGLtobuildtheshape.We //dothisbycreatingaFloat32ArrayfromtheJavaScriptarray, //thenuseittofillthecurrentvertexbuffer. gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(vertices),gl.STATIC_DRAW); //Setupthenormalsforthevertices,sothatwecancomputelighting. cubeVerticesNormalBuffer=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesNormalBuffer); varvertexNormals=[ //Front 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, //Back 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, 0.0,0.0,-1.0, //Top 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, 0.0,1.0,0.0, //Bottom 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, //Right 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,0.0, //Left -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0, -1.0,0.0,0.0 ]; gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(vertexNormals), gl.STATIC_DRAW); //Mapthetextureontothecube'sfaces. cubeVerticesTextureCoordBuffer=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesTextureCoordBuffer); vartextureCoordinates=[ //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); //Buildtheelementarraybuffer;thisspecifiestheindices //intothevertexarrayforeachface'svertices. cubeVerticesIndexBuffer=gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,cubeVerticesIndexBuffer); //Thisarraydefineseachfaceastwotriangles,usingthe //indicesintothevertexarraytospecifyeachtriangle's //position. varcubeVertexIndices=[ 0,1,2,0,2,3,//front 4,5,6,4,6,7,//back 8,9,10,8,10,11,//top 12,13,14,12,14,15,//bottom 16,17,18,16,18,19,//right 20,21,22,20,22,23//left ] //NowsendtheelementarraytoGL gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, newUint16Array(cubeVertexIndices),gl.STATIC_DRAW); } // //initTextures // //Initializethetextureswe'llbeusing,theninitiatealoadof //thetextureimages.ThehandleTextureLoaded()callbackwillfinish //thejob;itgetscalledeachtimeatexturefinishesloading. // //TODO#1Start functioncreateCubeTexture(text){ //createahiddencanvastodrawthetexture varcanvas=document.createElement('canvas'); canvas.id= hiddenCanvas ; canvas.width=512; canvas.height=512; canvas.style.display= none ; varbody=document.getElementsByTagName( body )[0]; body.appendChild(canvas); //drawtexture varcubeImage=document.getElementById('hiddenCanvas'); varctx=cubeImage.getContext('2d'); ctx.beginPath(); ctx.rect(0,0,ctx.canvas.width,ctx.canvas.height); ctx.fillStyle='white'; ctx.fill(); ctx.fillStyle='black'; ctx.font= 65pxArial ; ctx.textAlign='center'; ctx.fillText(text,ctx.canvas.width/2,ctx.canvas.height/2); ctx.restore(); //createnewtexture vartexture=gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,texture); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_NEAREST); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,true); handleTextureLoaded(cubeImage,texture) returntexture; } //TODO#1End functionhandleTextureLoaded(image,texture){ gl.bindTexture(gl.TEXTURE_2D,texture); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_NEAREST); gl.generateMipmap(gl.TEXTURE_2D); gl.bindTexture(gl.TEXTURE_2D,null); } // //drawScene // //Drawthescene. // functiondrawScene(){ //Clearthecanvasbeforewestartdrawingonit. gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); //Establishtheperspectivewithwhichwewanttoviewthe //scene.Ourfieldofviewis45degrees,withawidth/height //ratioof640:480,andweonlywanttoseeobjectsbetween0.1units //and100unitsawayfromthecamera. perspectiveMatrix=makePerspective(45,640.0/480.0,0.1,100.0); //Setthedrawingpositiontothe identity point,whichis //thecenterofthescene. loadIdentity(); //Nowmovethedrawingpositionabittowherewewanttostart //drawingthecube. mvTranslate([0.0,0.0,-6.0]); //Savethecurrentmatrix,thenrotatebeforewedraw. mvPushMatrix(); mvRotate(cubeRotation,[1,0,1]); //Drawthecubebybindingthearraybuffertothecube'svertices //array,settingattributes,andpushingittoGL. gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesBuffer); gl.vertexAttribPointer(vertexPositionAttribute,3,gl.FLOAT,false,0,0); //Setthetexturecoordinatesattributeforthevertices. gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesTextureCoordBuffer); gl.vertexAttribPointer(textureCoordAttribute,2,gl.FLOAT,false,0,0); //Bindthenormalsbuffertotheshaderattribute. gl.bindBuffer(gl.ARRAY_BUFFER,cubeVerticesNormalBuffer); gl.vertexAttribPointer(vertexNormalAttribute,3,gl.FLOAT,false,0,0); //Specifythetexturetomapontothefaces. gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D,cubeTexture); gl.uniform1i(gl.getUniformLocation(shaderProgram, uSampler ),0); //Drawthecube. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,cubeVerticesIndexBuffer); setMatrixUniforms(); gl.drawElements(gl.TRIANGLES,36,gl.UNSIGNED_SHORT,0); //Restoretheoriginalmatrix mvPopMatrix(); //Updatetherotationforthenextdraw,ifit'stimetodoso. varcurrentTime=(newDate).getTime(); if(lastCubeUpdateTime){ vardelta=currentTime-lastCubeUpdateTime; cubeRotation+=(30*delta)/1000.0; } lastCubeUpdateTime=currentTime; } // //initShaders // //Initializetheshaders,soWebGLknowshowtolightourscene. // functioninitShaders(){ varfragmentShader=getShader(gl, shader-fs varvertexShader=getShader(gl, shader-vs //Createtheshaderprogram shaderProgram=gl.createProgram(); gl.attachShader(shaderProgram,vertexShader); gl.attachShader(shaderProgram,fragmentShader); gl.linkProgram(shaderProgram); //Ifcreatingtheshaderprogramfailed,alert if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){ alert( Unabletoinitializetheshaderprogram. } gl.useProgram(shaderProgram); vertexPositionAttribute=gl.getAttribLocation(shaderProgram, aVertexPosition gl.enableVertexAttribArray(vertexPositionAttribute); textureCoordAttribute=gl.getAttribLocation(shaderProgram, aTextureCoord gl.enableVertexAttribArray(textureCoordAttribute); vertexNormalAttribute=gl.getAttribLocation(shaderProgram, aVertexNormal gl.enableVertexAttribArray(vertexNormalAttribute); } // //getShader // //Loadsashaderprogrambyscouringthecurrentdocument, //lookingforascriptwiththespecifiedID. // functiongetShader(gl,id){ varshaderScript=document.getElementById(id); //Didn'tfindanelementwiththespecifiedID;abort. if(!shaderScript){ returnnull; } //Walkthroughthesourceelement'schildren,buildingthe //shadersourcestring. vartheSource= ; varcurrentChild=shaderScript.firstChild; while(currentChild){ if(currentChild.nodeType==3){ theSource+=currentChild.textContent; } currentChildcurrentChild=currentChild.nextSibling; } //Nowfigureoutwhattypeofshaderscriptwehave, //basedonitsMIMEtype. varshader; if(shaderScript.type== x-shader/x-fragment ){ shader=gl.createShader(gl.FRAGMENT_SHADER); }elseif(shaderScript.type== x-shader/x-vertex ){ shader=gl.createShader(gl.VERTEX_SHADER); }else{ returnnull;//Unknownshadertype } //Sendthesourcetotheshaderobject gl.shaderSou更多编程语言

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表