WebGL基本图形图元生成演示(2/10)
3D应用的基础元素:
1、Canvas,它是渲染场景的占位符。标准html的canvas元素
2、Objects,这里指的是组成一个场景的所有3d实体。这些实体都由三角形组成。webgl中使用Buffer(vertex、index)来存储管理这些3d实体数据。
3、Lights,如果没有光照3d场景将看不到任何东西。webgl使用着色器来为场景中的光照建模。我们将会看到3d实体如何根据物理规律来反射和吸收光照,并讨论不同的光照模型。
4、Camera,摄像机作为3d世界的视口。我们通过摄像机来开发和看到一个3d场景。我们要理解如何根据不同的场景来使用不同的矩阵操作,这些操作可以利用相机原理来建模。
webgl中的数据类型:
webgl对图形有一种标准的处理方式,与我们拥有的表面的复杂性和顶点个数无关。只有两种基础的数据类型来表达3d物体的几何形状:vertices和indices(顶点和索引)。
Vertices: 代表3d物体的拐点,每一个顶点使用3个数字来表达想x,y,z;webgl中没有提供api来将独立的顶点传递到渲染管线中,因此我们需要将所有的顶点放在一个JavaScript数组中然后通过这个数组来构造一个webgl顶点缓冲区(vertex buffer)。
Indices: 索引是在一个给定3d场景的中的所有顶点的数字标识。索引告诉webgl如何有序的来链接顶点来生成一个表面。像顶点一样,索引也是存储在JavaScript数组中然后使用webgl索引缓冲区传递给webgl的渲染管线。
有两种webgl 缓冲区来描述和处理几何图形:
包含顶点数据的缓冲区:Vertex Buffer Objects(VBO)
包含索引数据的缓冲区:Index Buffer Objects(IBO)
webgl的渲染管线:
1.jpg
Vertex Buffer Objects
VBO包含了webgl要求来描述将要渲染的几何图形的数据。除了上面提到的顶点坐标外,还有vertex normal(顶点法线),颜色、纹理坐标等都可以用vbo来建模。
Vertex shader
顶点着色器将会来每个顶点上被调用,顶点着色器将用来操作之前的顶点数据,如顶点坐标、法线、颜色、文理坐标。这些数据将被顶点着色器内置的attributes变量来引用,每一个attribute指向一个他读取顶点数据的VBO。
Fragment shader
每三个顶点定义了一个三角形在三角形表面的每一个元素都需要被分配一个颜色,否则我们的表面将是透明的。
三角形表面的每一个元素成为一个片元(fragment)。因为我们处理的表面将被呈现在我们屏幕上,所以片元通常被理解为像素。
片元着色器的主要目的是为表面的每个独立像素来计算颜色。
2.jpg
Framebuffer
它是包含一个之前被片元着色器处理的片元二维的缓冲区。一旦所有的片元都被处理过后,一张二维图片将被构造并显示在屏幕上。framebuffer是渲染管道的最终点。
Attributes,uniforms,varyings是着色器编程中经常用到的三种类型的变量。
Attributes是顶点着色器中的输入变量,如顶点坐标、顶点颜色等。由于顶点着色器将会在每个顶点上都被调用,所以每次顶点着色器被调用时的输入变量attributes都是不同的。
Uniforms 是在顶点着色器和片元着色器中都能被使用的输入变量。在一个渲染循环中unifroms通常是不变的常量。如灯源位置。
Varyings用来由顶点着色器向片元着色器传递数据。
1、webgl缓冲区数据处理流程:
ver vertices = [];
var myBuffer = gl.createBuffer(); // 创建缓冲区
// 绑定缓冲区; 由于webgl是一个状态机,一旦绑定buffer,之后所有的缓冲操作都将在绑定的buffer上执行,直到解绑这个buffer或者绑定到另一个buffer上。
gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer);
// 绑定缓冲区后我们需要为他分配内容,webgl不能直接使用JavaScript数组,而是使用类型数组,以便缓冲区对象能够使用原生二进制数据来加快图形处理速度。
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);// 清空缓存
2、将attributes连接到VBOs
VBO创建后,我们需要将这些缓冲区链接到顶点着色器的属性中。每一个顶点着色器的attribute将且仅将指向一个缓冲区对象。
通常来讲我们有以下对应关系。
3.jpg
缓冲区数据进入顶点着色器分为三步:
1)绑定一个缓冲区:gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer)
2 ) 将一个attribute指向刚刚绑定的VBO:gl.vertexAttribPointer(Index, Size, Type, Norm, Stride, Offset);(该函数定义了一个从当前绑定缓冲区读取信息的指针;参数Index指的是将被匹配缓冲区的attribute的索引)
3)激活attribute:gl.enableVertexAttribArray(aVertexPosition)
下面的图表记录了匹配过程
4.jpg
3、渲染
定义完VBO对象并绑定到顶点着色器属性后,就可以准备渲染了。完成渲染过程我们可以使用两个API函数:drawArrays、drawElements
这两个方法都是用来像帧缓冲区中写入数据;drawArrays按照在缓冲区中的顶点数据的顺序来创建图形,相反drawElements使用索引来访问顶点缓冲区中的数据来创建图形。
drawArrays和drawElements仅接受 enabled arrays ,他们是被匹配到激活的顶点着色器attribute的vbo对象。
当索引信息无法获得时,我们使用drawArrays方法。在大多数情况下当几何图形很简单以至于定义索引是浪费资源时我们使用drawArrays方法,比如三角形、矩形。
5.jpg
使用drawArrays只适合非常简单的图形,如果是连续三角形,那么vbo中需要重复定义每个顶点,并且这些点都会在顶点着色器中被处理,浪费空间和性能。
gl.drawArrays(Mode, First, Count)
drawElements允许使用IBO来告诉浏览器如何去渲染图形。因为有了索引VBO中的数据不用像之前一样被重复定义,只需要定义一次,但可以通过索引来多次使用。这种方式减少内存和GPU的性能损耗。
6.jpg
使用drawElements至少需要两个Buffer:VBO和IBO;顶点着色器将在每一个VBO的顶点上执行,然后渲染管线使用IBO将几何图形聚集成三角形。(确保VBO、IBO都被绑定过)
gl.drawElements(Mode, Count, Type, Offset)
webgl作为一个状态机的buffer控制
我们可以拿到一些关于渲染管线状态的信息,比如:
getParameter(type)
ARRAY_BUFFER_BINDING取得一份关于最近绑定的VBO的引用
ELEMENT_ARRAY_BUFFER取得一份关于最近绑定的IBO的引用
getBufferParameter(type, parameter)
type: ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER
parameter: BUFFER_SIZE, BUFFER_USAGE
isBuffer(object)
基本步骤:
initProgram()
initBuffers()
drawSence()
创建着色器三步骤:
var shader = gl.createShader();
gl.shaderSource(shader, source);
gl.compileShader(shader);
gl.getShaderParameter(shader, gl.COMPILE\_STATUS);
initProgram步骤:
prg = gl.createProgram();
gl.attachShader(prg, shader); // vs fs
gl.linkProgram(prg);
gl.getProgramParameter(prg, gl.LINK\_STATUS)
gl.useProgram(prg);
prg.aVertexPosition = gl.getAttribLocation(prg, ‘aVertexPosition’);
WEBGL学习网 » WebGL基本图形图元生成演示(2/10)