我一直在试用一些WebGL但是有一个我似乎无法找到如何修复的错误。
目前我有以下设置:
我有大约100个三角形,它们都有一个位置,并由一个gl.drawArrays
函数绘制。为了按照正确的顺序绘制它们,我使用gl.enable(gl.DEPTH_TEST);
得到了正确的结果。
我现在遇到的问题是,如果我在顶点着色器中更新三角形的gl_Position
,则更新的Z值不会在深度测试中使用。结果是一个gl_Position.z
为1的三角形可以绘制在一个三角形的顶部,gl_Position.z
为10,这不是我想要的......
我尝试了什么?
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.GEQUAL);
带
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.clearDepth(0);
gl.drawArrays(gl.TRIANGLES, 0, verticesCount);
在渲染功能中。
以下代码用于创建缓冲区:
gl.bindBuffer(gl.ARRAY_BUFFER, dataBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positionBufferData, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, false, 0, 0);
z值较高的三角形的大小要大得多(由于透视),但小三角形仍然出现在它上面(由于渲染顺序)。
在片段着色器中,我使用gl_fragCoord.z
来查看是否正确,较小的三角形(距离较远)收到的alpha值高于较大的三角形(近距离)。
奇怪的绘画行为可能是什么原因?
答案 0 :(得分:0)
剪辑空间中的深度从-1变为1.写入深度缓冲区的深度从0变为1.您将清除为1.没有深度值> 1所以您应该看到的唯一内容是gl_Position.z = 1
。小于1的任何内容都将无法通过测试gl.depthFunc(gl.GEQUAL);
。什么> 1将被剪裁。只有1在深度范围内且大于或等于1
下面的示例绘制具有不同z值的较小到较大的矩形。红色为标准gl.depthFunc(gl.LESS)
,深度清除为1.绿色为gl.depthFunc(gl.GEQUAL)
,深度清除为0.蓝色为gl.depthFunc(gl.GEQUAL)
,深度清除为1.注意蓝色仅绘制单个矩形在gl_Position.z = 1
,因为所有其他矩形都未通过测试,因为它们处于Z <1。 1。
const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl");
const vs = `
attribute vec4 position;
varying vec4 v_position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
v_position = abs(position);
}
`;
const fs = `
precision mediump float;
varying vec4 v_position;
uniform vec4 color;
void main() {
gl_FragColor = vec4(1. - v_position.xxx, 1) * color;
}
`;
// compiles shaders, links program, looks up attributes
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBindbuffer, gl.bufferData for each array
const z0To1BufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: [
...makeQuad( .2, 0.00),
...makeQuad( .4, .25),
...makeQuad( .6, .50),
...makeQuad( .8, .75),
...makeQuad(1.0, 1.00),
],
});
const z1To0BufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: [
...makeQuad(.2, 1.00),
...makeQuad(.4, .75),
...makeQuad(.6, .50),
...makeQuad(.8, .25),
...makeQuad(1., 0.00),
],
});
function makeQuad(xy, z) {
return [
-xy, -xy, z,
xy, -xy, z,
-xy, xy, z,
-xy, xy, z,
xy, -xy, z,
xy, xy, z,
];
}
gl.useProgram(programInfo.program);
gl.enable(gl.DEPTH_TEST);
gl.clearDepth(1);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.LESS);
drawRects(-0.66, z0To1BufferInfo, [1, 0, 0, 1]);
gl.clearDepth(0);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.GEQUAL);
drawRects(0, z1To0BufferInfo, [0, 1, 0, 1]);
gl.clearDepth(1);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.depthFunc(gl.GEQUAL);
drawRects(0.66, z1To0BufferInfo, [0, 0, 1, 1]);
function drawRects(xoffset, bufferInfo, color) {
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
let mat = m4.translation([xoffset, 0, 0]);
mat = m4.scale(mat, [.3, .5, 1]);
// calls gl.uniformXXX
twgl.setUniforms(programInfo, {
color: color,
matrix: mat,
});
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
}
&#13;
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<canvas></canvas>
<pre>
red : depthFunc: LESS, clearDepth: 1
green: depthFunc: GEQUAL, clearDepth: 0
blue : depthFunc: GEQUAL, clearDepth: 1
</pre>
&#13;