绘制调用之间的深度缓冲区清除行为?

Depth Buffer Clear Behavior between Draw Calls?

我一直在测试 WebGL 以查看我是否可以以特定方式批量绘制多边形。我将简化用例,但它遵循以下内容:

首先,我的顶点很简单:

  vertices[v0_xy0, v1_xyz, ... vn_xyz]

在我的例子中,每个顶点的 z 值必须在 (0 - 100) 范围内(我任意选择 100),因为我希望使用这些 z 值对所有这些顶点进行深度测试。在批次 N + 1 上,我再次被限制为深度值 (0 - 100),但我需要保证这批次中的顶点绘制在所有先前批次(顶点层)之上。换句话说,每个批次中的顶点都针对每个顶点进行了深度测试,但每个批次只是在前一个批次之上绘制,就好像没有深度测试一样。 起初我打算尝试绘制到带有帧缓冲区和深度缓冲区附件的纹理,绘制到 canvas,对下一组顶点重复,但我意识到我可能只能这样做:

// pseudocode
function drawBuffers()
  // clear both the color and the depth
  gl.clearDepth(1.0);
  gl.clear(gl.CLEAR_COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  // iterate over all vertex batches
  for each vertexBatch in vertexBatches do
    // draw the batch with depth testing
    gl.draw(vertexBatch);
    // clear the depth buffer
    /* QUESTION: does this guarantee that subsequent batches 
       will be drawn atop previous batches, or will the pixels be written at  
       random (sometimes underneath, sometimes above)?
    */
    gl.clearDepth(1.0);
    gl.clear(gl.DEPTH_BUFFER_BIT);
  endfor
end drawBuffers

我通过绘制两个重叠的四边形、清除深度缓冲区、向左和负 z 平移(试图 "go under" 前一批)并再次绘制两个重叠的四边形来测试上述内容。我 认为 这是有效的,因为我看到第二对四边形绘制在第一对前面,即使它们的 z 值落后于前一对的 z 值;

虽然我不确定我的测试是否可靠。会不会涉及一些未定义的行为?我的测试由于 clearDepth 设置和形状而起作用只是巧合吗? 我可以澄清一下,以便确认我的方法是否确实有效吗? 谢谢。

由于 WebGL 基于 OpenGL ES,请参阅 OpenGL ES 1.1 Full Specification, 4.1.6 Depth Buffer Test, page 104

The depth buffer test discards the incoming fragment if a depth comparison fails.

....

The comparison is specified with

void DepthFunc( enum func );

This command takes a single symbolic constant: one of NEVER, ALWAYS, LESS, LEQUAL, EQUAL, GREATER, GEQUAL, NOTEQUAL. Accordingly, the depth buffer test passes never, always, if the incoming fragment’s zw value is less than, less than or equal to, equal to, greater than, greater than or equal to, or not equal to the depth value stored at the location given by the incoming fragment’s (xw, yw) coordinates.


这意味着,如果深度缓冲区 glClearDepth 的清除值是 1.0(1.0 是初始值)

gl.clearDepth(1.0);

并且深度缓冲区被清除

gl.clear(gl.DEPTH_BUFFER_BIT);

而深度函数glDepthFuncLESSLEQUALLESS为初值)

gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL); 

然后绘制到任何 (xw, yw) 坐标的下一个片段将通过深度测试并覆盖存储在 位置的片段(xw, yw).

(当然 gl.BLEND 必须禁用并且片段必须在剪辑 space 中)