《WebGL编程指南》笔记

第二章

  1. gl.clearColor(red, green, blue, alpha) 用指定颜色清空背景,数值区间都是0.0到1.0
  2. gl.clear(gl.COLOR_BUFFER_BIT)清空绘图区域实际上是清空颜色缓冲区,gl.COLOR_BUFFER_BIT这个参数就是指定清空颜色缓存。
  3. attribute变量传输的是与顶点相关的数据,而uniform变量传输的是对于所有顶点都相同或与顶点无关的数据。attribute变量是一种GLSL ES变量,被用来从外部向顶点着色器内传输数据,只有顶点着色器能使用它。
  4. 在使用辅助函数initShaders在WebGL系统中建立了顶点着色器后,WebGL会对顶点着色器进行解析,可以辨别出着色器中的attribute变量,可以用gl.getAttribLocation(gl.program, 'a_Position');获取变量的地址(这里有个先后关系,必须要建立着色器之后才能使用gl.program参数)。获取变量地址后给该变量赋值(存数据到变量的地址中), gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
  5. 两个坐标不一样,需要自己转换坐标
  6. gl.vertexAttrib3f()是一系列同族函数中的一个,该函数的任务就是从js向顶点着色器中的attribute变量传值
  7. clickedpoints例子中每次点击的坐标都记录下来了,并不是点击一次绘制一个点,而是每次点击都将之前的点绘制了一遍。原因是,webgl使用的是颜色缓冲区,系统中的绘制操作实际上是在颜色缓冲区中绘制的,绘制结束后系统先将缓冲区中的内容显示在屏幕上,然后颜色缓冲区就会被重置其中的内容会丢失。因此每次都必须gl.clear(gl.COLOR_BUFFER_BIT)手动重置缓冲区背景色绘制背景色,绘制背景以及之前点击过的点

第三章

  1. 使用缓冲区对象向顶点着色器传入多个顶点数据的步骤:创建缓冲区对象、绑定缓冲区对象、将数据写入缓冲区对象、将缓冲区对象分配给一个attribute变量开启attribute变量
  2. gl.drawArrays(mode, first, count)这个方法十分强大。webgl中只能绘制点、线、三角形,其中mode就是指定绘制的类型
  3. 旋转矩阵,逆时针(角度为正)旋转p度,顺时针旋转角度为负值
  4. 平移矩阵。平移变换过程中,存在常量项,使用3x3的矩阵无法表示常量,因此这里要使用4x4的矩阵
  5. webgl中矩阵元素以列为主序存储在数组中
  6. 缩放矩阵

第五章

  1. 从顶点着色器向片元着色器传递变量。在Webgl中,如果在顶点着色器与片元着色器中有同类型和命名一样的varying变量,顶点着色器给该变量赋的值会自动传入片元着色器
  2. 顶点着色器到片元着色器之间的过程
    gl_Position是几何图形装配阶段的输入数据,根据gl.drawArrays的第一个参数装配出图形后,将这个图形光栅化,得到片元。光栅化过程结束之后,开始逐片元调用片元着色器
  3. 顶点着色器中的v_color变量和片元着色器中v_color变量只是同名,但是性质不一样。顶点着色器中v_color变量是每个顶点的颜色值,而片元着色器中的v_color是颜色值经过插值之后每个片元的颜色值
  4. webgl中的纹理坐标系统和之前提到的webgl坐标系统以及canvas的坐标系统都不一样,进行纹理粘贴时也要注意进行坐标映射

第六章 GLSL ES语言

  1. 大小写敏感
  2. 只有数值和布尔值两种数值类型
  3. 强类型语言
  4. 支持矢量和矩阵类型
  5. 支持结构体,使用关键字struct定义结构体。结构体变量可以使用**==运算符进行比较,但是只有当结构体变量中所有成员都相等**时才返回true
  6. GLSL ES只支持一维数组,并且不支持pop()和push(),创建数组不需要new运算符。声明数组是需要在变量名后加上中括号和数组长度,但是数组长度必须是大于0的整型常量表达式。不能使用const限定字来修饰数组本身。只有整型常量表达式和uniform变量可以被用作数组的索引值,另外数组不能在声明时一次性地初始化,必须显示地对每个元素进行初始化
  7. 不允许递归调用,这样是为了编译器能对函数进行内联展开
  8. 可以为函数参数指定限定字
  9. attribute变量只能出现在顶点着色器中,只能被声明为全局变量,被用来表示逐顶点的信息。attribute变量的类型只能是float、vec2、vec3、mat2、mat3、mat4。顶点着色器能够容纳的attribute变量的最大数目与设备有关
  10. uniform变量可以用在顶点着色器和片元着色器中,且必须是全局变量,只读,可以是除了数组或结构体之外对任意类型。unidorm变量包含“一致”(非逐顶点逐片元)的数据
  11. varying变量必须是全局变量,数据类型和attribute一样。varying变量用来从顶点着色器向片元着色器传输数据,必须在两种着色器中声明同名同类型的varying变量。如第五章第3点描述的,顶点着色器中赋给varying变量的值并不是直接传给了片元着色器的varying变量,是根据图形绘制,进行插值之后再传递给片元着色器的。正式因为varying变量需要被插值,所以需要限定它的数据类型
  12. GLSL ES新引入了精度限定字,目的是帮助着色器程序提高运行效率,削减内存开支。只有片元着色器中的float类型没有默认精度。

第七章 三维世界

  1. 三维空间中物体是立体的,需要考虑视点(观察者的位置)、观察目标点(和视点一起构成视线)、上方向(只确定视点和目标点时,两点确定一条线,在不确定上方向点时候观察者还是可以绕着线旋转,这样看到的视图还是不唯一)。这样才能最终确定一个三维立体结构在二维平面上的视图。
  2. 从指定视点观察旋转后的三角形
  3. 水平视角垂直视角可视深度定义了可视空间。即限制了观察者视线的水平范围、垂直范围和能够看到的最远的距离
  4. 正射投影和透视投影。正射投影的好处是用户可以方便地比较场景中物体的大小,物体看上去的大小和物体所在的位置没有关系。透视投影可以使场景具有深度感。
  5. 正射投影中的可视空间如下图所示。正射投影的可视空间是个立方体,前后两个面分别成为近裁剪面远裁剪面。画布上显示的就是可视空间中物体在近裁剪面上的投影,如果裁剪面的宽高比和画布不一样,那么画面就会按照画布的宽高比进行压缩。如果将近裁剪面的宽和高都缩小为原来的一半,将看到显示的三角形相比原来看到的扩大了一倍,如果只将近裁剪面的宽缩小为原来的一半,则看到画布上三角形的宽扩大一倍。这是因为画布上显示的就是可视空间物体在近裁剪面上的投影,投影在画布上时,宽和高都会适应画布的宽和高,有可能会导致画面的宽高比和原来的不一致,表现如下图所示。定义正射投影时只需要定义下图中的top、right、bottom、left以及near和fear,这样来确定正射投影的可视空间。
  6. 透视投影的可视空间如下图所示。可以根据fov(可视空间顶面和底面间的夹角)、aspect(近裁剪面的宽高比)以及near、far(近裁剪面和远裁剪面的位置)来确定透视投影下的可视空间。其中和正射投影中一样,为了投影在画布上时画面不变性,最好将aspect设置成画布的宽高比。
  7. 当再加入投影矩阵时,最后顶点在视图坐标系下的坐标将是投影矩阵x视图矩阵x模型矩阵x顶点矩阵。可以这样理解,顶点最终的位置,是顶点初始坐标进行坐标变化后判断是否还在可视空间中后,再投影到画布上形成的。正射投影中,投影矩阵只用规范不在可视空间盒子中的物体可见,而透视投影中,投影矩阵要对顶点坐标进行一系列的基本变换来达到看到的近大远小以及向视线中心靠拢的效果(模型矩阵、视图矩阵和投影矩阵都封装在cuon-matrix.js中)
  8. 默认情况下,webgl为了加速绘图操作,是按照顶点在缓冲区中的顺序处理顶点,并不能自动的按照坐标来显示正确的前后关系。需要使用webgl中的隐藏面消除功能。其中gl.clear()方法用来清除深度缓冲区,如果要进行隐藏面消除就必须知道每个几何图形的深度信息,在绘制任意一帧前都必须清除深度缓冲区。
  9. webgl中当两个物体表面很接近是,会产生深度冲突(Z fighting)。原因是当两个物体太接近时,深度缓冲区有限的精度无法区分像素的前后。webgl中有多边形偏移(polygon offset)的机制,即给z值加上一个唯一的偏移量。
  10. 如何绘制一个立方体。绘制两个两个三角形拼成立方体的一个表面,使用gl.drawArrays()方法绘制,指定参数为gl.TRIANGLES时,需要在缓冲区中指定2x3x6=36个顶点,其中一些顶点的坐标是冗余的。指定参数为gl_TRIANGLE_FAN时,4个顶点绘制一个四边形,需要顶点数为4x6=24,这样顶点数减少了,但是这样的话需要调用6次绘制。使用gl.TRIANGLE_STRIP的话只需要绘制一次,存14个顶点坐标数据(3+1x11)。还有一种方法是,将绘制中的顶点用索引代替,顶点的坐标另外存在一个缓冲区中,这样就不会有冗余的顶点坐标信息。只需要一个如下的对应结构。顶点数据和面的顶点索引分开存,索引数据绑定的缓冲区对象换成gl.ELEMENT_ARRAY_BUGGER,这个参数告诉webgl,该缓冲区中的内容是顶点的索引值数据,最后绘制图形时使用gl.drawElements。使用这种方式节省了内存开销,但是需要通过索引间接地访问顶点
  11. 在绘制每个面颜色不同的立方体时,需要考虑到顶点同时在被三个面使用,因此此时只能将顶点分开处理,会有一些冗余。这样索引表中将会有24个顶点的索引。

第八章 光照

  1. 常见的光源类型有平行光(用一个方向和一个颜色定义)、点光源(点光源的位置和颜色定义)和环境光(只需要指定颜色)。
  2. 反射光的颜色取决于入射光(方向和颜色)和物体表面的类型(物体表面的颜色和反射特性)。物体表面的反射光线有漫反射和环境反射。漫反射在每个方向上的强度相等,如下图所示。在漫反射中,反射光的颜色取决于入射光的颜色、表面的基底色、入射光与表面形成的入射角<漫反射光线>=<入射光颜色>x<表面基底色>xcosa。环境反射中反射光的方向可以认为是入射光的反方向,因此和入射光一样,反射光也是个方向均匀且强度相等,<环境反射光颜色>=<入射光颜色>x<表面基底色>。当这两种反射同时存在时,将两者加起来(???)就是最终看到的颜色,<表面的反射光颜色>=<漫反射光颜色>+<环境反射光颜色>
  3. 上面提到的漫反射中需要用到入射角的余弦值,但是不可能确切的知道每个点的入射角是多少。可以根据入射光的方向和物体的法线方向计算入射角。两个向量n(xn,yn,zn)和l(xl,yl,zl)做点积运算,几何上表示为n . l = |n| x |l| x cosa,代数上表示为n . l = xn x xl + yn x yl + nz x lz,光线方向矢量和表面法线矢量的长度为1时,点积计算的结果就是cosa的值,只需要在顶点片元中加入该计算即可。
  4. 三维图形学中,绘制了v0、v1、v2、v3四个点,从正面看时这4个点是顺时针,由此确定表面的正面和反面。
  5. lightedcube的例子中,顶点着色器中,计算最终的入射光的余弦值时,有一个和0取大值的操作。点积小于0的时候代表入射角大于90度,也就是光线照在表面的背面,此时直接将赋值为0就行了。
  6. 在例子lightedCube_animation中,可以看到立方体转动的过程中,颜色过渡很生硬,该例子中的光照只考虑到了直射上去的平行光,而没有考虑到环境光。环境光可以想像成从各个方向均匀的照在物体表面,因此由环境光反射产生的颜色只取决于光的颜色和物体表面的基底色
  7. 将顶点变换之前的法向量乘以模型矩阵的逆转置矩阵就得到对顶点通过模型矩阵进行变换之后的法向量。???(数学知识的补充:如果矩阵M的逆矩阵是R,那么R*M或M*R的结果都是单位矩阵。转置是将矩阵的行列进行调换。)
  8. 当光源是点光源时,每个顶点处的光线方向都不同,此时要在顶点着色器中计算该顶点处的光线方向,在知道顶点坐标和光源坐标的情况下,矢量相减就可以得到光线方向。但是这里存在一个问题,webgl中除了顶点之外的面上的其它点的颜色都是webgl插值计算出来的,平行光时直接使用内插值不会有什么问题,但是点光源照射下,每个点的处的光线角度不一样,直接内插和实际的效果会有区别。因此在点光源照射下,可以改成逐片元的光照。在顶点着色器中处理顶点坐标,并在片元着色器中定义同名的变量,这样就可以得到内插之后逐片元的变量???其余的计算方式一样。有多个点光源的时候需要相同的计算进行多次,并最后相加。

转载于:https://juejin.im/post/5ba46bd7e51d450e5a7406f0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值