webGL初步了解,最简单的方式了解webgl
Posted 天霸学ccc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webGL初步了解,最简单的方式了解webgl相关的知识,希望对你有一定的参考价值。
前述
1.webGL是什么?
WebGL(全写 Web Graphics Library )是一种 3D 绘图标准,这种绘图技术标准允许把 javascript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定, WebGL 可以为 html5 Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型了,还能创建复杂的导航和数据视觉化。显然, WebGL 技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂 3D 结构的网站页面,甚至可以用来设计 3D 网页游戏等等。
天霸认为webGL跟openGL是一样一样的,学习webGL,对于我们了解游戏引擎原理会很有帮助,可以说我们学会了webGL或者openGL之后,做一些游戏特效会更加的得心应手,比如说棋牌游戏的翻牌效果,rpg游戏中的刀光剑影等等。
第一步,环境
不需要环境,是的研究webgl根本不需要环境,只要你拥有一台电脑,不管是windows系统的还是macos系统的,甚至是手机,只要你的手机可以写代码也可以的。
第二步,创建文件
我们首先选择一个代码编辑器吧,我建议大家选择webstrom 或者是vscode,不过你喜欢用windows自带的文本编辑器写,那也不是不可以。
天霸这里使用的是webstrom,因为webstorm可以再带一个webserver,首先我们随便找一个位置创建一个文件夹,然后用webstrom打开这个文件夹,就像图中这样
然后在在这里目录里面新建一个html文件,随便取一个名字,天霸用index.html作为文件名,看图!
第三步,写代码
1,写着色器
webGL渲染的过程需要好几种着色器,我这里就不一一列举了,有兴趣的小伙伴可以去自行百度,这里我主要讲两个着色器,也是我们可以操作的着色器(别的着色器我们都不能操作),一个是顶点着色器,一个是片段着色器也叫片元着色器,这里只是简单介绍一下这两个着色器的功能,详细原理还是自己去百度吧(我怕我说错了哈哈!), 顶点着色器是负责处理物体的每一个顶点的,意思就是说告诉我们的显卡,物体的每个顶点都处在那个位置,这里说的位置是三维坐标,x,y,z坐标,想象一下就得了,想多了头疼,片段着色器是告诉我们的显卡每一个像素点的值,也就是颜色。当然对于显卡来说,颜色没有意义,只有数值有意义,也就是说我们通过片段着色器告诉显卡一个像素点的值,包括四个值,rgba,通俗讲就是 红 绿 蓝 透明度这四个值,每个值占8个比特位,也就是说用十进制表示就是1-256 ,也就是2的8次方。(括号里面的内容是我猜的,大家意会一下就得了, 我们的显示器是有好多个像素点构成的,每一个像素点又是由三个基础像素都成的红绿蓝。正好我们的rgb这三个值可以控制三个基础像素的 亮暗程度。这样像素点多了,不就组成图形了么,反正是我猜的,对不对的不负责任啊),这样我们大概了解了这两个着色器的功能,但是我们应该怎么来写着色器呢,这就需要一个很重要的语言那就是GLSL,https://blog.csdn.net/jeffasd/article/details/77989274?locationNum=10&fps=1 可以点这里深入了解GLSL语言,
那GLSL到底是什么呢,它的全称是OpenGL Shading Language( 看到了么,其实webGL跟openGL是一样的 ,用的都是GLSL语言),我们知道编程语言就是我们程序员跟计算机交流的语言,就好比汉语或者英语 是跟人类交流的语言一样,只要掌握了一定的规律跟技巧,我们就可以让计算机很好的为我们服务,那再细分一下,javascript就是让cpu工作的语言,glsl就是让显卡工作的语言。厉害吧,我们学会了glsl ,就可以让直接让显卡为我们服务了,是不是很高大上,好了,那么就让我们写起来吧!
首先在我们的html文件里面写两个标签<script>标签,并且给他们分别加一个id属性一个叫
vShader
一个叫
fShader
当然这个可以按照个人喜好,就是爱叫啥就叫啥,然后我们给他们的type设置成
x-shader/x-fragment
这样我们的编辑器就可以知道我们正在写shader(就是着色器代码,glsl语言,后面简称shader)代码,会给我们一些高亮,虽然没有自动联想,全部代码是这样的
这样我们就可以写shader代码了,看我的命名方式就能看出,前一个标签里面主要装的是顶点着色器的代码,后一个标签里面装的是片段着色器的代码,因为我们写的shader代码要以字符串的形式发给我们的渲染程序,所以我们写在这个标签里面到时候取出他的内容就可以了,你也可以直接写字符串在后面的方法里面,只要你喜欢,下面是顶点着色器的代码。
是不是很简单,着色器都是必须有一个void main(){} 函数的,是不是有点像c语言,不要害怕没有c语言那么难。gl_Position,是一个内部变量,我们可以改变他的值。给他一个vec4这样的类型的一个值,了解详情去点击我开头给我那个链接,下面我们继续补全片段着色器的代码。
是不是很简单,当然现在还不能让显卡为我们工作,我们还得做一些操作,需要让cpu出来做一些配合。
2,启动webgl程序
让cpu工作的话就很简单了,就用我们最熟悉的语言 javascript,首先第一步我们先在我们的html文本里面加一个canvas标签在body标签里面,然后紧接着在canvas标签后面写一个script标签,来作为承载我们的javascript语言的地方,
好了,下面我们就开始写代码了,首先取出我们body里面的canvas,然后获取canvas的webgl支持,
let canvas =document.getElementById('canvas');
let gl = canvas.getContext('webgl');
这两句代码。我相信小伙伴们很容易理解,第一行是获取我们的canvas控件,第二行是获取canvas的绘图环境,他需要一个参数,这里我们写的是webgl,就是说我们要获取canvas上的webgl的绘图环境,当然为了严谨我们还需要加上一句代码
if(!gl){console.log('sorry your device not support webGL!')return}
这句就不解释了
然后我们继续,我们拿到gl之后呢,最先做的是什么呢,那就是创建我们的shader,首先创建我们的顶点着色器
let vShader = gl.createShader(gl.VERTEX_SHADER);
这一行是创建一个顶点着色器,gl可以创建着色器,但是得需要一个参数,他需要知道你想要什么类型的着色器(顶点着色器gl.VERTEX_SHADER,片段着色器gl.FRAGMENT_SHADER);
gl.shaderSource(vShader, document.getElementById('vShader').text);
这是链接着色器代码,就是之前写的那个shader代码,也就是glsl语言写的,我们通过document获得vShader标签然后访问他的text属性就行了,这样我们就取到了shader代码。
gl.compileShader(vShader);
链接好之后我们就可以编译了,当然编译的话也有可能会编译失败,但是我们不能在着色器语言里面打断点也不能打log,所以webgl给我们提供了相应的debug的一些接口
if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS)){
console.log('vShader compile fail ' + gl.getShaderInfoLog(vShader));
}
不解释,目前的代码是这样的:
上面这些就是创建一个顶点着色器并且编译的一个过程,然后我们继续创建片段着色器,创建片段着色器跟顶点着色器类似,只是参数不一样,所以我们将上面这几行代码改造一下,来方便我们创建着色器。
function createShader(gl, shaderType, shaderCode){
let shader = gl.createShader(shaderType);
gl.shaderSource(gl, shaderCode);
gl.compileShader(shader);
if (gl.getShaderParameter(shader , gl.COMPILE_STATUS)){
console.log('compile shader fail ' + gl.getShaderInfoLog(shader));
return;
}
return shader;
}
现在的全部代码是这样的:
那么我们只需要调用一下这个方法,就可以很快的创建一个shader了。
let vShader = createShader(gl, gl.VERTEX_SHADER, document.getElementById('vShader').text);
let fShader = createShader(gl, gl.FRAGMENT_SHADER,document.getElementById('fShader').text);
这两句就不解释了。
下面我们来创建一个渲染程序。
let program = gl.createProgram();
分别将两个着色器绑定到渲染程序上
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
然后将渲染程序链接到我们的webgl上
gl.linkProgram(program);
目前代码是这样的:
接下来呢,我们创建缓冲区(这里是我意淫的,为了帮助大家理解,对不对的不负责任。所谓缓冲区,就是一段显存区域,我们将数据写入缓存,然后显卡按照一定的方式取出显存里面的数据并通过一定的方式将数据绘制到显示器上面)创建缓冲区并绑定数据的方式是这样的
let buffer = gl.createBuffer();
创建缓冲区
gl.bindBuffer( gl.ARRAY_BUFFER,buffer);
显卡里面有好多种缓冲区,我们这里绑定到ARRAY_BUFFER缓冲区。
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array(
[0,0,
1,0,
1,1]
) , gl.STATIC_DRAW
);
绑定缓冲区数据,第一个是指定缓冲区的类型也可以理解成位置,第二个是缓冲区数据,这里是Float32Array格式的数据,里面是一个数组,这里其实是一个三角新,看书写格式可以理解成三角形的三个顶点坐标,第三个参数是渲染模式。
最后告诉gl我们要使用这个程序了
gl.useProgram(program);
然后是最后一步了,给我们的着色器加一个属性,方便我们传一个参数到着色器里面,那么具体的代码就是这样的。
let positionLocation = gl.getAttribLocation(program, 'a_position');
获取到着色器里面的一个属性,在着色器代码里面的属性要以 attribute字段声明
gl.enableVertexAttribArray(positionLocation);
启动我们的着色器属性
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0,0);
这是告诉gl通过什么样的方式来处理我们的属性参数。参数分别是,属性,尺寸,类型,是否归一化,起点,偏移,具体含义还是得去点击开始我贴的链接。
最后一步我们就可以调用渲染程序了
gl.drawArrays(gl.TRIANGLE, 0, 3);
这句就是说让gl去渲染我们的缓冲区,第一个参数是画的是一个什么形状,这里的参数代表的是三角形。第二个参数我也不知道是干什么的,第三个参数是3,是渲染的次数,因为之前我们绑定的缓冲区数据是一个6个长度的数组对吧,但是我们告诉缓存去每次读取几个数据呢,2个,就是vertexAttribPointer这个的第二个参数,6除2 就是3,就是说我们需要渲染3次才能将我们的缓冲区绑定的数据都渲染完。不能理解的话我也没有办法。我也很头疼。
到目前为止所有让cpu干活的代码就完成了,但是这时候我们还不能进行测试,我们还需要稍微改一下我们的顶点着色器。因为我们的顶点着色器还没有接收参数的操作。
给我们的顶点着色器代码,加上一个属性参数。
这样我们就将我们绑定的缓冲区数据通过属性的方式传送到我们的顶点着色器里面了,我们就可以使用这个数据了。这时候我们点击编辑器里面右上角的浏览器按钮
如果你的浏览器出现了下面的画面,
说明你成功的用webGL在浏览器里面绘制了一个三角形,当然webGL的功能肯定不局限于画这么一个简单的三角形。看似简单的一个图形,我们却做了这么多的工作,那么我们要绘制更加复杂的图形怎么办,那必定会更加的复杂。所以就出现了各式各样的游戏引擎,来帮助我们把这些复杂的操作简单化,让我们把精力都放在内容创作上,但是有人要问了,既然已经有了游戏引擎帮我们做这些事情了,那我们还学习webGL有什么意义呢,因为毕竟引擎的功能有限,我们要实现更加酷炫的效果,光靠引擎是远远不够的,还需要从底层出发来实现我们想要的效果。还有我们理解了一些原理之后,对于我们的游戏的性能的优化会有举足轻重的作用。
代码可能看不太清,https://github.com/haoyuan336/gongzhonghaoWebGL可以直接打开链接去下载源码。喜欢的小伙伴点个赞哦!
----------------------------------------------
以上是关于webGL初步了解,最简单的方式了解webgl的主要内容,如果未能解决你的问题,请参考以下文章