> 文章列表 > webgl渲染优化——深度缓冲区、多边形缓冲机制

webgl渲染优化——深度缓冲区、多边形缓冲机制

webgl渲染优化——深度缓冲区、多边形缓冲机制

文章目录


前言

webgl在渲染三维场景时,按照Z坐标的值决定前后关系,但是在默认状态下它并未开启深度检测,而是将后绘制的物体放在前面;当两个物体Z坐标相差无几时,会产生深度冲突,两个物体颜色互相影响,使得表面看上去斑斑驳驳,需要开启多边形缓冲来避免此类问题。


深度缓冲区

我们知道webgl着色器中的内置变量gl_Position是按照左手坐标系。也就是说Z轴指向屏幕内侧,z坐标大的像素将会被绘制在后方,遮挡z坐标比它大的像素(暂不考虑乘以MVP矩阵)。但是,这是在开启深度检测的前提下,如果没有开启这一设置,后绘制的会遮挡先前绘制的
这样子使用:

	/ @type {HTMLCanvasElement} *///------------------------------------------------------创建画布// 获取canvas元素对象let canvas = document.getElementById('canvas');// 获取webgl绘图上下文const gl = canvas.getContext('webgl');if (!gl) {throw new Error('WebGL not supported');}gl.viewport(0, 0, canvas.width, canvas.height)// 设置背景色gl.clearColor(0.0, 0.0, 0.0, 1.0)// 清空缓冲区gl.clear(gl.COLOR_BUFFER_BIT)const vertex = `attribute vec4 aPosition;attribute vec4 aColor;varying vec4 v_Color;void main() {gl_Position =  aPosition;gl_PointSize = 10.0;v_Color = aColor;}`const fragment = `precision highp float;varying vec4 v_Color;void main(){gl_FragColor = v_Color;}`// 创建programconst program = initShader(gl, vertex, fragment)// 获取attribute变量的数据存储位置const aPosition = gl.getAttribLocation(program, 'aPosition');const aColor = gl.getAttribLocation(program, 'aColor');// 获取uniform变量的数据存储位置// 创建缓冲区对象const buffer = gl.createBuffer();// 绑定缓冲区对象gl.bindBuffer(gl.ARRAY_BUFFER, buffer);// 传入的数据const vertices = new Float32Array([// Z 为 0.0的蓝色三角形-0.3, 0.6, 0.0, 0.4, 0.4, 1.0, -0.8, -0.6, 0.0, 0.4, 0.4, 1.0,0.2, -0.6, 0.0, 1.0, 0.4, 0.4,// Z 为 -0.5的黄色三角形0.0, 1.0, -0.5, 1.0, 1.0, 0.4, -0.5, -1.0, -0.5, 1.0, 1.0, 0.4,0.5, -1.0, -0.5, 1.0, 0.4, 0.4,// Z 为 0.5 的绿色三角形0.3, 0.8, 0.5, 0.4, 1.0, 0.4, -0.2, -0.8, 0.5, 0.4, 1.0, 0.4,0.8, -0.8, 0.5, 1.0, 0.4, 0.4,])const BYTES = vertices.BYTES_PER_ELEMENT;// 开辟空间并写入数据gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)// 缓冲区对象分配给attribute变量gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 6 * BYTES, 0)gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 6 * BYTES, 3 * BYTES)// 开启attribue变量gl.enableVertexAttribArray(aPosition)gl.enableVertexAttribArray(aColor)// 开始绘制gl.drawArrays(gl.TRIANGLES, 0, 18)

在上述代码中,向vertices依次传入缓冲区数据,实际效果如下:

webgl渲染优化——深度缓冲区、多边形缓冲机制

webgl默认按照缓冲区中的顺序绘制图形,后绘制的图形覆盖先绘制的图形,因为这样做很高效。但是当传入顺序与z坐标大小不一致,或者视点不断移动更改视角时,将无法保证绘制顺序。

  • 开启深度检测
  • 1.开启隐藏面消除功能:gl.enable(gl.DEPTH_TEST)
  • 2.在执行绘制函数之前,清除深度缓冲区:gl.clear(gl.DEPTH_BUFFER_BIT),gl.clear支持使用 | 添加多个参数。
		// 设置背景色gl.clearColor(0.0, 0.0, 0.0, 1.0)// 开启深度检测gl.enable(gl.DEPTH_TEST);// 清空颜色缓冲区和深度缓冲区gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )

如下黄色就到了最前面
webgl渲染优化——深度缓冲区、多边形缓冲机制
为了方便观察蓝色三角形与绿色三角形的关系,将黄色三角形尺寸调整的小一些:

		const vertices = new Float32Array([// Z 为 0.0的蓝色三角形-0.3, 0.6, 0.0, 0.4, 0.4, 1.0, -0.8, -0.6, 0.0, 0.4, 0.4, 1.0,0.2, -0.6, 0.0, 1.0, 0.4, 0.4,// Z 为 -0.5的黄色三角形0.0, 0.2, -0.5, 1.0, 1.0, 0.4, -0.5, -0.2, -0.5, 1.0, 1.0, 0.4,0.5, -0.2, -0.5, 1.0, 0.4, 0.4,// Z 为 0.5 的绿色三角形0.3, 0.8, 0.5, 0.4, 1.0, 0.4, -0.2, -0.8, 0.5, 0.4, 1.0, 0.4,0.8, -0.8, 0.5, 1.0, 0.4, 0.4,])

效果如下,与预计中一样,Z坐标:Z黄 < Z蓝 < Z绿。前后顺序:黄 > 蓝 > 绿。

webgl渲染优化——深度缓冲区、多边形缓冲机制

多边形缓冲机制

当两个表面过于接近,深度缓冲区有限的精度已经不能区分先后关系,当场景中有多个运动着的物体时,很难保证它们的深度值不会在某刻相同,这种情况会导致两个物体颜色互相影响,使得表面看上去斑斑驳驳。

webgl渲染优化——深度缓冲区、多边形缓冲机制

webgl提供一种名为 多边形偏移 的机制来解决这个问题。该机制将自动在 Z 值加上一个偏移量,偏移量的值由物体表面相对于观察者视线的角度来确定。

  • 1.开启多边形偏移:gl.enable(gl.POLYGON_OFFSET_FILL)
  • 2.设置偏移参数:gl.polygonOffset(1.0, 1.0)
  gl.enable(gl.POLYGON_OFFSET_FILL);gl.polygonOffset(1.0, 1.0);  

webgl渲染优化——深度缓冲区、多边形缓冲机制

总结

  • 深度缓冲区

  • 多边形缓冲机制