WebGL ThreeJS学习总结一、二

https://github.com/newbieYoung/NewbieWebArticles/blob/master/webgl-threejs-1-2.html(2017-08-31T12:35:50Z)

© Young 2016-10-18 07:57
Welcome to My GitHub

概述

在写这篇总结之前,这已经是我第二次尝试学习WebGL了,第一次是在两年前,那时候正在从事Java开发相关工作,觉得没什么意思,然后平时工作中有接触到一些前端相关的东西,刚好那时HTML5很火,就稍微了解了一下Canvas,然后自然而然的知道了WebGL,刚开始学的时候感觉很吃力,然后就买了本书《WebGL入门指南》,虽然跟着书上的例子也能照葫芦画瓢弄个正方体出来,但是总感觉实现了某个例子,依然啥也不会,没多久就放弃了。

现在已经从事前端开发工作接近两年,在前不久看到一篇博客后再次燃起了学习WebGL的热情,然后采购了一本书《WebGL编程指南》,花了一周时间看了100多页之后,差点再次放弃,思考了一下午决定改进下学习方法。

结合这两次的从准备入门到放弃的经验来看,单独学习ThreeJS容易给人造成不知其然的感觉,而单独学习WebGL又太枯燥,所以我决定把二者结合起来,先根据《WebGL编程指南》学习WebGL感觉枯燥之后就参照ThreeJS官方文档以及官方源代码中的例子学习ThreeJS并找些相对容易实现的例子实现,在这过程中写一些学习总结。

总结一主要是了解一些WebGL的基本概念,然后通过示例程序学习WebGL程序的基本结构、GLSL语言以及编写一些简单的WebGL程序。

概念

一、基本概念

1、WebGL起源

在个人计算机上使用最广泛的两种三维图形渲染技术是Direct3D和OpenGL,其中WebGL就是从OpenGL的一个特殊版本OpenGL ES中派生出来的,后者专用于嵌入式计算机、智能手机、家用游戏机等设备。

2、WebGL程序结构

在HTML中动态网页包括HTML和JavaScript两种语言,在引入WebGL后,还需要加入着色器语言GLSL ES。

3、WebGL坐标系

暂时认为WebGL坐标系为右手坐标系,即当你面朝计算机屏幕时,X轴是水平的(正方向为右),Y轴是垂直的(正方向为上),Z轴垂直于屏幕(正方向为外)。

4、WebGL颜色分量取值范围

在平时前端开发中我们一般使用的颜色分量取值范围是从0到255,但是由于WebGL是继承自OpenGL,所以它遵循传统OpenGL颜色分量的取值范围,即从0.0到1.0。

5、WebGL坐标取值范围

坐标取值范围与颜色分量的取值范围一样也是从0.0到1.0。

个人理解:取值范围从0.0到1.0其实可以看成从0%到100%,之所以取值范围是这样,可能是为了适应计算机硬件的发展吧,比如颜色分量取值范围如果固定为某个具体数值,随着硬件的发展能识别更多颜色之后就会有兼容性的问题。

6、齐次坐标

齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w),暂时理解为齐次坐标能提高三维数据的运算效率,在GLSL ES中使用vec4类型表示。

7、着色器

WebGL需要两种着色器;

顶点着色器,顶点着色器是用来描述顶点特性(如位置、颜色等)的程序;

片元着色器,进行逐片元处理过程(如光照)的程序。

8、片元

暂时理解成像素即可。

9、网格

绘制3D图形的方法有很多,最常用的一种方法就是使用网格(Mesh),这也是为什么下边的程序示例是绘制三角形的原因。

10、矩阵

虽然上大学时没好好学,但是网上资料挺多,就不一一拷贝了。

理解矩阵乘法

11、顶点着色器和片元着色器之间图形装配和光栅化的过程

  • 执行顶点着色器,传入缓冲区对象中的第一个顶点坐标,一旦赋值成功,该数据就进入了图形装配区域,并暂时存储在那里;

  • 重复执行顶点着色器直到所有顶点数据赋值完成;

  • 开始装配图形(按照一定的规则把所有顶点连接起来);

  • 将图形转化为片元,这个过程被称为光栅化,光栅化是三维图形学的关键技术之一,它负责将矢量的几何图形转变为栅格化的片元

补充解释下光栅化,其实就是把矢量图形转化成像素点的过程,因为最常用的一种绘制3D图形的方法就是使用网格(Mesh),也就是点线面属于矢量图形,而当前屏幕是像素渲染的,那么从矢量图形转化成用户所看到的像素图像必然需要光栅化这一步骤。

  • 光栅化结束之后,程序就开始逐片元调用片元着色器,每调用一次就处理一个片元,片元着色器会计算出该片元的颜色,并写入颜色缓冲区;

  • 当最后一个片元处理完成,浏览器就会显示最终结果。

另外这个过程如果我们使用当前流行的ThreeJS框架可以理解如下:

其中黄色区域是ThreeJS框架中使用JS实现的,绿色部分是THreeJS框架中使用GLSL ES实现的。

12、缓冲区对象

对于那些由多个顶点组成的图形,比如三角形、矩形等,你需要一次性地将图形的顶点全部传入顶点着色器,然后才能把图形画出来,WebGL提供了一种很方便的机制,即缓冲区对象(是WebGL系统中的一块内存区域),它可以一次性地向着色器传入多个顶点数据。

使用缓冲区对象时需要遵循以下五个步骤:

创建缓冲区对象(gl.createBuffer());
绑定缓冲区对象(gl.bindBuffer());
将数据写入缓冲区对象(gl.bufferData());
将缓冲区对象分配给着色器变量(gl.vertexAttriPointer());
启动着色器变量(gl.enableVertexAttriArray())。

使用多个缓冲区对象向着色器传递多种数据,比较适合数据量不大的情况,当数据量很大时这种方式很难维护,所以WebGL允许我们把不同种类的数据打包到同一个缓冲区对象中,并通过某种机制分别访问缓冲区对象中不同种类的数据。

13、纹理坐标

纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色,WebGL系统中的纹理坐标系统是二维的,为了将纹理坐标和广泛使用的x坐标和y坐标区分开来,使用s和t命名,称之为st坐标系统。

14、纹理映射

纹理映射的一般步骤:

准备好映射到几何图形上的纹理图像;
为几何图形配置纹理映射方式;
加载纹理图像,对其进行一些配置,以在WebGL中使用它;
在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋予片元。

在配置纹理映射的时候需要注意一点,图片坐标系统和WebGL纹理坐标系统的Y轴方向是相反的,这时候你需要对纹理图像进行Y轴反转;

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);// Flip the image’s y-axis

15、纹理单元

WebGL通过一种纹理单元的机制来同时使用多个纹理,每个纹理单元有一个单元编号来管理一张纹理图像,系统支持的纹理单元个数取决于硬件和浏览器的WebGL实现,默认情况下至少支持8个纹理单元。

使用纹理单元的一般步骤:

激活纹理单元(gl.activeTexture());
绑定纹理对象(gl.bindTexture());
配置纹理对象的参数(gl.texParameteri());
将纹理图像分配给纹理对象(gl.texImage2D());
将纹理单元编号传递给取样器。

16、FrameBuffer

有点类似于Canvas中的离屏渲染,一般我们使用gl.drawArrays或者gl.drawElements都是将对象绘制在了默认的窗口中,但是当我们指定一个FrameBuffer时,再用这个两个方法去绘制,则会将对象会绘制于当前指定的FrameBuffer。

一般用于纹理的多重处理,比如对于一个纹理我们可以先灰度过滤,然后再模糊过滤,但是灰度过滤后还不能直接渲染到屏幕上,则可以使用FrameBuffer过渡,直到处理完成之后再渲染到屏幕上;
使用范例可以去WebGL简单实现高斯模糊这个例子中查看。

二、GLSL

1、attribute变量和uniform变量

都是GLSL ES中的变量类型,使用这两种变量可以把数据从JavaScript程序中传给着色器程序;

attribute和uniform类似都是存储限定符,主要区别如下:attribute只能用于顶点着色器,用来表示逐顶点数据;uniform可以用于顶点着色器也可以用于片元着色器,用来表示不变的数据。

uniform表示不变的数据的意思是在GLSL程序内部不能再被改变,但是可以再次由JavaScript程序赋予新的值。

2、按行主序和按列主序

在编程时我们通常使用数组存储矩阵,但是矩阵是二维的,数组是一维的,所以如果在数组中按行存储矩阵元素就被称为按行主序,在数组中按列存储矩阵元素就被称为按列主序;

WebGL和OpenGL一样,矩阵元素是按列主序存储在数组中的。

3、varying变量以及颜色值内插

暂时理解为varying变量的作用是从顶点着色器向片元着色器传输数据;

颜色值内插暂时就理解为颜色自动渐变(如果想要深入了解内插过程,可以参考《计算机图形学》)。

示例程序

发表评论

电子邮件地址不会被公开。 必填项已用*标注