更新于 

深度

正确处理对象的前后关系

WebGL能自动分析出三维对象的远近吗?

答: 不能。
WebGL不能正确处理遮挡关系,后绘制的图形总是覆盖先绘制的图形。
WebGL为了加速绘图操作,优先按照顶点在缓冲区的顺序进行处理(处理遮挡关系的话需要对顶点数据进行打乱重排吗?)。

打乱PerspectiveView的缓冲区顶点顺序绘制效果如何?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let verticesColors = new Float32Array([
// 蓝色
0.0, 1.0, 0.0, 0.4, 0.4, 1.0,
-0.5, -1.0, 0.0, 0.4, 0.4, 1.0,
0.5, -1.0, 0.0, 1.0, 0.4, 0.4,
// 黄色
0.0, 1.0, -2.0, 1.0, 1.0, 0.4,
-0.5, -1.0, -2.0, 1.0, 1.0, 0.4,
0.5, -1.0, -2.0, 1.0, 0.4, 0.4,
// 绿色
0.0, 1.0, -4.0, 0.4, 1.0, 0.4,
-0.5, -1.0, -4.0, 0.4, 1.0, 0.4,
0.5, -1.0, -4.0, 1.0, 0.4, 0.4,
]);
后绘制的图形覆盖了先绘制的图形
后绘制的图形覆盖了先绘制的图形

隐藏面消除

隐藏面消除(hidden surface removal)

具体功能: 消除被遮挡的表面,已经被内嵌在WebGL中。

开启方式

难道就不能给个Boolean属性直接表示开启或关闭吗?恼啊!

隐藏面消除前提

必须要先设置可视空间,无论是正射还是透视类型。

1.开启隐藏面消除功能

1
gl.enable(gl.DEPTH_TEST);

2.绘制前清除深度缓冲区

1
gl.clear(gl.DEAPTH_BUFFER_BIT);
enable和disable

enable用来开启WebGL汇总的多种功能,disable与之相反。

cap的取值不止这些

更多可参阅OpenGL Programming Guide一书。

为什么说深度缓冲区是个中间对象?

答: 想一想,如果要根据顶点的深度坐标对图形进行隐藏面消除,
那首先就要知道 每个几何图形的深度信息,深度缓冲区就是用来存储 深度信息 的。

为什么隐藏面消除功能要命名为DEAPTH_TEST?

答: 因为该功能的实现原理就是通过检测(Test)物体每个像素的深度(Depth)来决定是否绘制的。

深度缓冲区的清空时机

答: 在绘制任意一帧之前都要清除深度缓冲区。
同时清除两个缓冲区时,可以使用 按位或操作 进行简化。

1
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
DepthBuffer Code
开启DEPTH_TEST后,实现了隐藏面消除
开启DEPTH_TEST后,实现了隐藏面消除
1
2
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

深度冲突

深度冲突(Z fighting)

指的是物体两个表面极为接近时,绘制出来的表面斑驳不平滑。
原因是在表面过于接近时,深度缓冲区有限精度不足以区分前后。

这种问题最容易出现在场景中有多个运动着的物体时。

多边形偏移(polygon offset)

是WebGL用于解决深度冲突的方式。
实现原理: 自动在Z值上加一个偏移量,该值由 物体表面相对于观察者视线的角度 来确定。

多边形偏移机制的启用(2步)

1.启用多边形偏移

1
gl.enable(gl.POLYGON_OFFSET_FILL);

2.绘制之前指定计算偏移量的参数

1
gl.polygonOffset(1.0,1.0);
1
gl.polygonOffset(factor,units) = m * factor + r * units;
  • m 表示顶点所在表面相对于观察者的视线的角度
  • r 表示硬件能够区分两个z值之差的最小值
Zflighting
Zflighting Code
1
2
3
pvMatrix.setPerspective(
30, canvas.width / canvas.height, 1.0, 100.0
);
1
2
3
pvMatrix.lookAt(
3,0,10, 0, 0, -6, 0, 1, 0
);
1
2
3
4
5
6
7
8
9
10
11
let verticesColors = new Float32Array([
// 绿色三角形
0.0, 2.5, -5.0, 1.0, 1.0, 0.0,
-2.5, -2.5, -5.0, 0.0, 1.0, 0.0,
2.5, -2.5, -5.0, 0.0, 1.0, 0.0,

// 蓝色三角形
0.0, 3.0, -5.0, 0.0, 0.0, 1.0,
-3.0, -3.0, -5.0, 0.0, 1.0, 1.0,
3.0, -3.0, -5.0, 0.0, 1.0, 1.0,
]);
多边形偏移前后对比
多边形偏移前绘制结果
多边形偏移前绘制结果
1
2
3
4
gl.enable(gl.POLYGON_OFFSET_FILL);
gl.drawArrays(gl.TRIANGLES, 0, n/2); // draw green triangle
// gl.polygonOffset(1.0, 1.0); // set polygon offset
gl.drawArrays(gl.TRIANGLES, n/2, n/2); // draw blue triangle
多边形偏移后绘制结果
多边形偏移后绘制结果
1
2
3
4
gl.enable(gl.POLYGON_OFFSET_FILL);
gl.drawArrays(gl.TRIANGLES, 0, n/2); // draw green triangle
gl.polygonOffset(1.0, 1.0); // set polygon offset
gl.drawArrays(gl.TRIANGLES, n/2, n/2); // draw blue triangle