WebGL着色器z位置未用于深度计算

时间:2017-04-08 10:03:48

标签: webgl depth-buffer zbuffer

我一直在试用一些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值高于较大的三角形(近距离)。

奇怪的绘画行为可能是什么原因?

1 个答案:

答案 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。

&#13;
&#13;
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;
&#13;
&#13;