2017-04-08 100 views
0

我一直在嘗試一些WebGL,但有一個錯誤,我似乎無法找到如何解決。WebGL着色器z位置未用於深度計算

目前我有以下設置: 我有大約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

爲什麼將與Z A三角形= 1不被過度地z = 10的三角形繪製? 1 ** IS **小於或等於10. – BDL

+0

我想要一個更高的Z值在上面,這實際上應該是'gl.GEQUAL',那麼好點。深度測試在我更新的'gl_Position'上仍然不起作用。 –

+0

請在問題中發佈工作片段。 SO要求:「尋求調試幫助的問題(」爲什麼這個代碼不工作?「)必須包含所需的行爲,特定的問題或錯誤以及**在問題本身中重現*所需的最短代碼*** 。 – gman

回答

0

深度在clipspace從-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.

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); 
 
}
<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>

+0

我測試了不同的組合,發現depthFunc GEQUAL和clearDepth的1仍然有效,這意味着每個三角形的z值都是1.然而,問題是我的所有三角形都繪製在一個drawArrays函數中, Z在頂點着色器中定義。我如何得到這個工作?目前在您的解決方案中,訂單仍然不正確。 –

+0

在我的例子中,訂單正是我所期望的。我使用'LESS'繪製紅色z = 0.1 - > 1.0,其中0.1很小,1.0很大,我看到大圖在小圖的後面,意味着深度緩衝區按預期工作。綠色是z = 1.0到0.1,其中1.0小,0.1大。這次我使用'GEQUAL'。再次,因爲我畫了0.1最後,它是最大的,這表明它按預期工作。它不覆蓋z = 1.0處的小東西,因爲深度緩衝區正在工作並被清除爲0. – gman

+0

最後一個(藍色)顯示深度緩衝區是否被清除爲1,那麼只有1.0處的東西能夠工作(第一個小矩形)。所有其他人不工作,因爲他們低於1.0,測試是'GEQUAL'。在你的例子中,你至少需要清除0而不是1,否則除了z = 1之外什麼都不能繪製。 – gman