物体旋转
使用模型视图投影矩阵变化顶点坐标。
根据鼠标位移差值,计算旋转矩阵。
1 | viewProjMatrix.setPerspective() |
选中物体
使用颜色缓冲区方法(简单)
当点击时,整个对象重绘成单一红色。
读取鼠标点击处的颜色。
使用立方体原来的颜色重绘。
对比第二步读取到的颜色。
1 | gl.readPixels(x, y, width, height, format, type, pixels) |
例如对于立方体的多个表面,将表面编号写入组成每个表面各个顶点,将编号数组传入顶点着色器。当点击时,首先在顶点着色器中将每个面根据编号计算每个面的颜色α值,并在颜色缓冲区中重绘。即可通过readPixels
获取颜色值,得到点击的表面编号。之后根据表面编号,再传入顶点着色器对相应面进行所需操作。
HUD(平视显示器)
再三维场景上叠加文本或者二维图形信息。
使用两个canvas叠加。背景透明。
雾化
线性雾化:雾化程度取决于与视点之间的距离。某一点的雾化程度可以定义成雾化因子。
片元颜色 = 物体表面颜色 x 雾化因子 + 雾的颜色 x (1 - 雾化因子)
w分量
gl_Position的w分量为顶点的视图坐标的z分量乘以-1。在视图坐标系中,视点在原点,视线沿着Z轴负方向,观察者看到的物体其视图坐标系值z分量都为负数,所以其w值可以直接近似为顶点与视点的距离。
绘制圆形点
将方形的点剔除不需要的片元。
片元着色器中内置变量
1 | vec4 gl_FragCoord //片元窗口坐标 |
在片元着色器中,将距离点的中心(0.5,0.5)超过0.5的片元剔除。
1 | distance(gl_PointCoord, vec2(0.5, 0.5)) //计算距离函数 |
α混合
实现半透明效果,需要用到颜色的α分量。需要开启WebGL的α混合功能。
1 | gl.enable(gl.BLEND) //开启混合功能 |
混合函数
混合后的颜色 = 源颜色 * src_factor + 目标颜色 * dst_factor
源颜色: 待混合进去的颜色。上层颜色
目标颜色: 待被混合的颜色。下层颜色
透明与不透明共存
透明后如果开启了隐藏面消除功能,则被隐藏的片元则不会绘制。所以不会发生混合过程。但是关闭隐藏面消除功能会使物体前后关系乱套。所以要实现透明与不透明共存:
- 开启隐藏面消除功能
gl.enable(gl.DEPTH_TEST)
- 绘制所有不透明物体
- 锁定用于隐藏面消除的深度缓冲区的写入操作,使其只读。深度缓冲区: 是一个中间对象,帮助进行隐藏面消除,存储深度信息:每个像素的归一化坐标z值。其对比z值,舍弃隐藏的片元,不会写入颜色缓冲区。
gl.depthMask(false)
- 绘制所有半透明物体,需要按照深度排序,从后往前绘制。
- 释放深度缓冲区,可读可写。
gl.depthMask(true)
切换着色器
当对于不同物体需要不同着色器进行绘制时,需要切换使用。
为多个着色器对象创建多个程序对象,使用gl.useProgram(program)
进行切换。
渲染到纹理
加载三维模型
OBJ文件格式
(#)开头行为注释
材质文件存储在外部MTL格式文件。
mtllib<外部材质文件名>
模型名称
<模型名称>
顶点坐标
v x y z [w]
指定某个材质 。列举使用这个材质的表面。材质被定义在引用的MTL文件中。
1
2
3
4 usemtl<材质名>
f v1 v2 v3 v4 ···
f v1//vn1 v2//vn2 v3//vn3 ···其中v1为顶点索引值,从1开始。
vn1,vn2为法线向量索引,从1开始。
MTL文件格式
定义一个新材质
newmtl<材质名>
使用Ka、Kd和Ks定义表面环境色、漫反射、高光色。使用RGB格式,区间为[0.0,1.0]
1
2
3 Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000Ns指定高光色权重,Ni指定表面光学密度,d指定透明度,illum指定光照模型。
响应上下文丢失
当其他程序接管了图形硬件,或者操作系统休眠,浏览器会失去这些资源,webgl绘图上下文就会丢失。
1 | webglcontextlost事件 当WebGL上下文丢失时触发 |
当丢失上下文时,getWebGLContext()
函数获得渲染上下文对象gl
就失效了。在浏览器重置WebGL后需要重新完成在之前gl
对象上的所有操作。如创建缓冲区,纹理对象,初始化着色器等。