• 售前

  • 售后

热门帖子
入门百科

HTML5之WebGL 3D概述(上)—WebGL原生开辟开启网页3D渲染新时代

[复制链接]
我就是但丁徊 显示全部楼层 发表于 2021-10-25 19:33:59 |阅读模式 打印 上一主题 下一主题
WebGL开启了网页3D渲染的新时代,它允许在canvas中直接渲染3D的内容,而不借助任何插件。WebGL同canvas 2D的API一样,都是通过脚本操纵对象,所以步调也是根本相似:预备工作上下文,预备数据,在canvas中绘制对象并渲染。与2D不同的就是3D涉及的知识更多了,比方世界、光线、纹理、相机、矩阵等专业知识。WebGL有一个很好的中文教程,就是下面利用参考中的第一个链接,所以这里不再班门弄斧,背面的内容只是简朴的总结一放学习的内容。
浏览器的支持
由于微软有本身的图形发展计划,不停不支持WebGL,所以IE现在除了安装插件外,是无法运行WebGL的。其他的主流浏览器如Chrome、FireFox、Safari、Opera等,都装上最新的版本就可以了。除了浏览器要装最新的外,还要包管显卡的驱动也是最新的。
装上这些以后,可以打开浏览器,输入下面的网址验证一下浏览器对WebGL的支持情况:http://webglreport.sourceforge.net/。
在正常安装以上浏览器之后照旧不能运行WebGL,那你可以强制开启WebGL支持试一试。开启方法如下:
Chrome浏览器
我们必要为Chrome参加一些启动参数,以下详细操作步调以Windows操作体系为例:找到Chrome浏览器的快捷方式,右键点击快捷方式,选择属性;在目标框内,chrome.exe背面的引号背面,参加以下内容:
--enable-webgl--ignore-gpu-blacklist--allow-file-access-from-files点击确定后关闭Chrome,然后用此快捷方式启动Chrome浏览器。
几个参数的含义如下:
--enable-webgl的意思是开启WebGL支持;
--ignore-gpu-blacklist的意思是忽略GPU黑名单,也就是说有一些显卡GPU由于过于陈旧等原因,不建议运行WebGL,这个参数可以让浏览器忽略这个黑名单,强制运行WebGL;
--allow-file-access-from-files的意思是允许从本地载入资源,如果你不是WebGL的开辟者,不必要开辟调试WebGL,只是想要看一下WebGL的Demo,那你可以不添加这个参数。
Firefox浏览器
Firefox的用户请在浏览器的地点栏输入“about:config”,回车,然后在过滤器(filter)中搜刮“webgl”,将webgl.force-enabled设置为true;将webgl.disabled设置为false;在过滤器(filter)中搜刮“security.fileuri.strict_origin_policy”,将security.fileuri.strict_origin_policy设置为false;然后关闭现在开启的全部Firefox窗口,重新启动Firefox。
前两个设置是强制开启WebGL支持,最后一个security.fileuri.strict_origin_policy的设置是允许从本地载入资源,如果你不是WebGL的开辟者,不必要开辟调试WebGL,只是想要看一下WebGL的Demo,那你可以不设置此项。
Safari浏览器
在菜单中找到“属性”→“高级”,选中“显示开辟菜单”,然后到“开辟”菜单,选中“开启WebGL”。
开辟步调
下面的代码只是简朴总结一下相关的概念,它来源于参考中的中文教程,涉及较多的3D方面的知识。感兴趣的同砚直接可以跳到实用参考中的中文教程中学习,比我这里讲解的要详细和精确的多。凑热闹的同砚简朴看看就可以了,不用深究每一行代码的含义。

预备工作
这个不用说了,就是在页面上添加一个canvas元素作为渲染的容器。比方:

复制代码代码如下:
<body>
<canvasid="glcanvas"width="640"height="480">
Yourbrowserdoesn'tappeartosupporttheHTML5canvaselement.
</canvas>
</body>

下面就是正式开始写脚本的时间了,起首看一下步调入口以及团体结构:

复制代码代码如下:
functionstart(){
varcanvas=document.getElementById("glcanvas");
initGL(canvas);
initShaders();
initBuffers();
gl.clearColor(0.0,0.0,0.0,1.0);
gl.enable(gl.DEPTH_TEST);
drawScene();
}

这里的几个方法代表了典型的WebGL的绘制步调:

步调一:初始化WebGL工作情况 - initGL
这个方法的代码如下:

复制代码代码如下:
vargl;
functioninitGL(canvas){
gl=null;
try{
//Trytograbthestandardcontext.Ifitfails,fallbacktoexperimental.
gl=canvas.getContext("webgl")||canvas.getContext("experimental-webgl");
}
catch(e){} //Ifwedon'thaveaGLcontext,giveupnow
if(!gl){
alert("UnabletoinitializeWebGL.Yourbrowsermaynotsupportit.");
}
}

这个方法很简朴,就是获取WebGL的绘制情况,必要把参数"webgl"传给canvas.getContext方法就行了,但是由于现在WebGL的标准没有终极定型,所以实验阶段用的参数都是"experimental-webgl"。固然你直接去调用canvas.getContext("experimental-webgl")也是可以的,等标准定下以后,你再修改一个代码。
步调二:初始化着色器Shaders - initShaders
着色器Shader概念比力简朴,说白了就是显卡运算指令。构造3D场景必要进行大量的颜色、位置等等信息的计算,如果这些计算由软件实验的话,速率会很慢。所以把这些运算让显卡去计算,速率就很快;如何去实验这些计算,就是由着色器指定的。着色器代码是用一种叫做GLSL的着色器语言编写的,这个我们不去陈诉这个语言了。
着色器可以在html中界说,在代码中利用。固然了你在步调中用一个字符串去界说着色器也是一样的。
下面先看界说的部分:

复制代码代码如下:
<scriptid="shader-fs"type="x-shader/x-fragment">
precisionmediumpfloat;
varyingvec4vColor;
voidmain(void){
gl_FragColor=vColor;
}
</script>
<scriptid="shader-vs"type="x-shader/x-vertex">
attributevec3aVertexPosition;
attributevec4aVertexColor;
uniformmat4uMVMatrix;
uniformmat4uPMatrix;
varyingvec4vColor;
voidmain(void){
gl_Position=uPMatrix*uMVMatrix*vec4(aVertexPosition,1.0);
vColor=aVertexColor;
}
</script>

这里有两个着色器:面着色器和顶点着色器。
关于这两个着色器,这里有必要分析一下,计算机中的3D模子根本都是由点联合三角面片去形貌的,顶点着色器就是行止理这些点的数据,而面着色器就是通过插值的方式,行止理三角面片上点的数据。
上面界说的顶点着色器就界说了顶点的位置和颜色计算方式;而面着色器界说了插值点的颜色计算方式。实际的应用场景中,还会涉及到在着色器中处置惩罚光线等效果。
界说了着色器,在步调中就可以查找到它们并可以去利用:

复制代码代码如下:
varshaderProgram;
functioninitShaders(){
varfragmentShader=getShader(gl,"shader-fs");
varvertexShader=getShader(gl,"shader-vs");
shaderProgram=gl.createProgram();
gl.attachShader(shaderProgram,vertexShader);
gl.attachShader(shaderProgram,fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){
alert("Couldnotinitialiseshaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute=gl.getAttribLocation(shaderProgram,"aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute=gl.getAttribLocation(shaderProgram,"aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform=gl.getUniformLocation(shaderProgram,"uPMatrix");
shaderProgram.mvMatrixUniform=gl.getUniformLocation(shaderProgram,"uMVMatrix");
}

着色器是有了,但是怎么让显卡去实验,Program就是这种桥梁,它是WebGL原生的二进制码,它的作用根本上就是让显卡运行着色器代码去渲问鼎定的模子数据。
这里还用到一个辅助方法getShader,这个方法就是遍历html文档,查找着色器的界说,拿到界说后创建着色器,这里就不细说了:

复制代码代码如下:
functiongetShader(gl,id){
varshaderScript,theSource,currentChild,shader;
shaderScript=document.getElementById(id);
if(!shaderScript){
returnnull;
}
theSource="";
currentChild=shaderScript.firstChild;
while(currentChild){
if(currentChild.nodeType==currentChild.TEXT_NODE){
theSource+=currentChild.textContent;
}
currentChild=currentChild.nextSibling;
}
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{
//Unknownshadertype
returnnull;
}
gl.shaderSource(shader,theSource);
//Compiletheshaderprogram
gl.compileShader(shader);
//Seeifitcompiledsuccessfully
if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){
alert("Anerroroccurredcompilingtheshaders:"+gl.getShaderInfoLog(shader));
returnnull;
}
returnshader;
}

步调三:创建/加载模子数据 - initBuffers
这些小例子中,模子数据根本都是直接天生的,实际的步调中,这些数据应该都是从模子加载得到的:

复制代码代码如下:
vartriangleVertexPositionBuffer;
vartriangleVertexColorBuffer;
functioninitBuffers(){
triangleVertexPositionBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);
varvertices=[
0.0,1.0,0.0,
-1.0,-1.0,0.0,
1.0,-1.0,0.0
];
gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(vertices),gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize=3;
triangleVertexPositionBuffer.numItems=3;
triangleVertexColorBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexColorBuffer);
varcolors=[
1.0,0.0,0.0,1.0,
0.0,1.0,0.0,1.0,
0.0,0.0,1.0,1.0
];
gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(colors),gl.STATIC_DRAW);
triangleVertexColorBuffer.itemSize=4;
triangleVertexColorBuffer.numItems=3;
}

上面这段代码创建了三角形的顶点和顶点的颜色数据并放在缓冲区中。

步调四:渲染 - drawScene
预备好了数据以后,交给WebGL去渲染就好了,这里调用的是gl.drawArrays方法。看代码:

复制代码代码如下:
functiondrawScene(){
gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
pMatrix=okMat4Proj(45.0,gl.viewportWidth/gl.viewportHeight,0.1,100.0);
mvMatrix=okMat4Trans(-1.5,0.0,-7.0);
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,triangleVertexPositionBuffer.itemSize,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,triangleVertexColorBuffer.itemSize,gl.FLOAT,false,0,0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES,0,triangleVertexPositionBuffer.numItems);
}

这个函数起首设置了3D世界的配景为黑色,然后设置投影矩阵,设置待绘制对象的位置,然后根据缓冲中的顶点和颜色数据,绘制对象。这里还有一些天生投影矩阵和模子视图矩形的辅助方法(利用了Oak3D图形库中的矩阵辅助方法)与主题关系不大,这里就不详细表明了。
根本上流程就是这么多了,更复杂的纹理,光线等都是在这些基础上参加一些WegGL的特性实现的,这个请参看背面的中文教程,内里有详细的例子。
怎么样?利用原生的WebGL开辟是一种什么感受?不仅必要有深厚的3D知识,还必要知道各种实现细节。WebGL如许做是为了灵活的顺应各种应用场景,但是对于大多数像我如许非专业人士来说,许多细节是不必要知道的。如许就催生了各种辅助开辟的类库,比方这节用到的Oak3D库(为了演示WebGL开辟,例子中只用到了矩阵辅助方法)。下一节会先容一个用的比力多的Three.js图形库。
实用参考:
中文教程:http://www.hiwebgl.com/?p=42
开辟中心:https://developer.mozilla.org/en/WebGL

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作