1.webgl中解决深度冲突-多边形偏移
1.什么是深度冲突?
就是当几何图形或者物体的两个表面极为接近时,就会使得表面看上去斑斑点点,这种现象就是 深度冲突。
看看这个缓冲区渲染出的效果
缓冲区数据
var verticesColors = new Float32Array([
// Vertex coordinates and color
0.0, 2.5, -5.0, 0.4, 1.0, 0.4, // The green triangle
-2.5, -2.5, -5.0, 0.4, 1.0, 0.4,
2.5, -2.5, -5.0, 1.0, 0.4, 0.4,
0.0, 3.0, -5.0, 1.0, 0.4, 0.4, // The yellow triagle
-3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
]);
效果
你看上面渲染出的两个三角形的颜色,斑斑驳驳的。
在看两个三角形的坐标 (x,y, -5) (x1, y1, -5) 这两个三角形的 z坐标都是 -5。
之所以会产生深度冲突,是因为两个表面过于接近,深度缓冲区的精度已经不能区分哪个在前,哪个在后。
2.解决方案 - 多边形偏移
该机制将会自动在z值加上一个偏移量,偏移量的值由物体表面相对于观察者视线角度来确定
1.启动多边形偏移
gl.enable(gl.POLYGON_OFFSEF_FILL);
2.在绘制之前指定用来计算偏移量的参数
gl.polygonOffset(1.0, 1.0);
效果图
是不是好多了
详细代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#canvas {
/* height: 400px; */
/* width: 400px; */
background-color: black;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script src="../lib/cuon-matrix.js"></script>
<script>
const gl = canvas.getContext('webgl');
const createShader = (type, source) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const compileState = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compileState) {
const info = gl.getShaderInfoLog(shader);
console.log('编译白痴信息为' + info)
gl.deleteShader(shader);
return null;
}
return shader
}
// const VSHADER_SOURCE =
// 'attribute vec4 a_Position;\n' +
// 'attribute vec4 a_Color;\n' +
// 'uniform mat4 u_ViewProjMatrix;\n' +
// 'varying vec4 c_Color;\n' +
// 'void main(){' +
// ' gl_Position = u_ViewProjMatrix * a_Position;\n' +
// ' c_Color = a_Color;\n' +
// '}\n'
// const FSHADER_SOURCE =
// '#ifdef GL_ES\n' +
// 'precision mediump float;\n' +
// '#endif\n' +
// 'varying vec4 c_Color;\n' +
// 'void main(){' +
// ' gl_FragColor = c_Color;\n' +
// '}'
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'uniform mat4 u_ViewProjMatrix;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_Position = u_ViewProjMatrix * a_Position;\n' +
' v_Color = a_Color;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision mediump float;\n' +
'#endif\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_FragColor = v_Color;\n' +
'}\n';
// createShader(gl.VERTEX_SHADER, VSHADER_SOURCE);
// createShader(gl.FRAGMENT_SHADER, FSHADER_SOURCE);
const createProgram = (vshader, fshader) => {
const vertexShader = createShader(gl.VERTEX_SHADER, vshader);
const fragementSaher = createShader(gl.FRAGMENT_SHADER, fshader);
if (!vertexShader || !fragementSaher) {
console.log('创建着色器失败')
return null
}
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragementSaher);
gl.linkProgram(program);
const linkState = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linkState) {
const err = gl.getProgramInfoLog(program);
console.log('链接报错信息为' + err);
gl.deleteShader(vertexShader);
gl.deleteShader(fragementSaher);
gl.deleteProgram(program);
return null
}
return program
}
const program = createProgram(VSHADER_SOURCE, FSHADER_SOURCE)
gl.useProgram(program);
gl.program = program;
// const initBuffers = () => {
// const data = new Float32Array([
// // 0.0, 0.0, 5.0, 1.0, 0.0, 0.0,
// // -0.75, 0.0, 5.0, 1.0, 0.0, 0.0,
// // 0.0, 0.75, 5.0, 1.0, 0.0, 0.0,
// // 0.5, 0.0, 5.0, 0.0, 1.0, 0.0,
// // -0.5, 0.0, 5.0, 0.0, 1.0, 0.0,
// // 0.0, 0.5, 5.0, 0.0, 1.0, 0.0,
// 0.0, 2.5, -5.0, 0.4, 1.0, 0.4, // The green triangle
// -2.5, -2.5, -5.0, 0.4, 1.0, 0.4,
// 2.5, -2.5, -5.0, 1.0, 0.4, 0.4,
// 0.0, 3.0, -5.0, 1.0, 0.4, 0.4, // The yellow triagle
// -3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
// 3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
// ])
// const size = data.BYTES_PER_ELEMENT;
// // const bufferData = gl.createBuffer();
// const bufferData = gl.createBuffer();
// gl.bindBuffer(gl.ARRAY_BUFFER, bufferData);
// gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
// const a_Color = gl.getAttribLocation(gl.program, 'a_Color');
// // gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, size * 6, 0);
// // gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, size * 6, 0);
// gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, size * 6, 0);
// gl.enableVertexAttribArray(a_Position);
// // gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, size * 6, size * 3);
// gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, size * 6, size * 3);
// gl.enableVertexAttribArray(a_Color);
// }
function initVertexBuffers(gl) {
var verticesColors = new Float32Array([
// Vertex coordinates and color
0.0, 2.5, -5.0, 0.4, 1.0, 0.4, // The green triangle
-2.5, -2.5, -5.0, 0.4, 1.0, 0.4,
2.5, -2.5, -5.0, 1.0, 0.4, 0.4,
0.0, 3.0, -5.0, 1.0, 0.4, 0.4, // The yellow triagle
-3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
3.0, -3.0, -5.0, 1.0, 1.0, 0.4,
]);
var n = 6;
// Create a buffer object
var vertexColorbuffer = gl.createBuffer();
if (!vertexColorbuffer) {
console.log('Failed to create the buffer object');
return -1;
}
// Write the vertex coordinates and color to the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
// Assign the buffer object to a_Position and enable the assignment
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);
gl.enableVertexAttribArray(a_Position);
// Assign the buffer object to a_Color and enable the assignment
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
if (a_Color < 0) {
console.log('Failed to get the storage location of a_Color');
return -1;
}
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);
return n;
}
initVertexBuffers(gl);
gl.clearColor(0, 0, 0, 1);
const u_ViewProjMatrix = gl.getUniformLocation(gl.program, 'u_ViewProjMatrix');
console.log(u_ViewProjMatrix)
var viewProjMatrix = new Matrix4();
viewProjMatrix.setPerspective(30, canvas.width / canvas.height, 1, 100);
// console.log(canvas.width/canvas.height, canvas.height, canvas.width, 'canvas.width/canvas.height')
viewProjMatrix.lookAt(3.06, 2.5, 10.0, 0, 0, -2, 0, 1, 0);
gl.uniformMatrix4fv(u_ViewProjMatrix, false, viewProjMatrix.elements);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.POLYGON_OFFSET_FILL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.polygonOffset(1.0, 1.0);
gl.drawArrays(gl.TRIANGLES, 3, 3);
</script>
</body>
</html>