Depth Test
Runnable luma.gl example: Depth Test. Open the live demo, read the complete source, and copy the file into your project. No build step or API key.
single HTML file · CDN dependencies onlyinterface may contain Chinese labels
Source
<!--
说明:三块重叠的四边形按「近→中→远」的顺序绘制,深度测试打开时近的始终压住远的
核心逻辑:parameters 里的 depthCompare 与 depthWriteEnabled 决定深度缓冲是否参与比较
依赖:@luma.gl/core 9.4.2、webgl、shadertools、engine · jsDelivr CDN(UMD)
-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="robots" content="noindex,follow">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>深度测试</title>
<style>
html,body{height:100%;margin:0;background:#0d1117}
body{display:flex;flex-direction:column;overflow:hidden;
font:13px/1.6 -apple-system,"Segoe UI","PingFang SC",sans-serif;color:#e6e8ec}
.bar{flex:0 0 auto;padding:8px 12px;background:#161b22;border-bottom:1px solid #252c36;
display:flex;gap:12px;align-items:center;font-size:12px;color:#8b93a1;flex-wrap:wrap}
.bar b{color:#58a6ff;font-weight:600}
.bar button{font:inherit;font-size:12px;padding:4px 10px;border-radius:5px;cursor:pointer;
border:1px solid #303845;background:#1d2531;color:#c8d2e0}
.bar button:hover{background:#253040}
.bar .sp{flex:1 1 auto}
.wrap{position:relative;flex:1 1 auto;min-height:0;display:flex}
#cv{flex:1 1 auto;min-height:0;width:100%;display:block}
#err{position:absolute;left:0;right:0;top:0;padding:16px;color:#ff9d85;
font:12px/1.7 ui-monospace,Consolas,monospace;white-space:pre-wrap;display:none}
</style>
</head>
<body>
<div class="bar">
<span>深度比较 <b id="cmp">less-equal</b></span>
<button id="toggle">关闭深度测试</button>
<span class="sp"></span>
<span>绘制顺序固定为 蓝 → 绿 → 红,只有深度能改变遮挡</span>
</div>
<div class="wrap">
<canvas id="cv"></canvas>
<div id="err"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@luma.gl/core@9.4.2/dist/dist.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@luma.gl/webgl@9.4.2/dist/dist.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@luma.gl/shadertools@9.4.2/dist/dist.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@luma.gl/engine@9.4.2/dist/dist.min.js"></script>
<script>
(function () {
'use strict';
var cv = document.getElementById('cv');
var errBox = document.getElementById('err');
function fail(msg) {
errBox.style.display = 'block';
errBox.textContent = '运行失败:' + msg;
}
if (!window.luma || !luma.Model || !luma.AnimationLoop) {
fail('luma.gl 未加载成功,请检查能否访问 cdn.jsdelivr.net');
return;
}
var positions = new Float32Array(18 * 3);
var colors = new Float32Array(18 * 3);
var cursor = 0;
/* 每块四边形六个顶点;裁剪空间里 z 越小离相机越近 */
function pushQuad(x0, y0, x1, y1, z, r, g, b) {
var corners = [
[x0, y0], [x1, y0], [x1, y1],
[x0, y0], [x1, y1], [x0, y1]
];
for (var i = 0; i < corners.length; i++) {
positions[cursor * 3] = corners[i][0];
positions[cursor * 3 + 1] = corners[i][1];
positions[cursor * 3 + 2] = z;
colors[cursor * 3] = r;
colors[cursor * 3 + 1] = g;
colors[cursor * 3 + 2] = b;
cursor++;
}
}
/* 蓝画在最前也最近;红最后画但最远,只有深度能把它压回去 */
pushQuad(-0.72, -0.18, 0.12, 0.62, -0.7, 0.26, 0.55, 0.98);
pushQuad(-0.12, -0.62, 0.72, 0.18, 0.0, 0.27, 0.86, 0.62);
pushQuad(-0.42, -0.38, 0.42, 0.38, 0.6, 0.98, 0.45, 0.38);
luma.luma.createDevice({
type: 'webgl',
adapters: [luma.webgl2Adapter],
createCanvasContext: {
canvas: cv,
useDevicePixels: Math.min(window.devicePixelRatio, 2),
autoResize: true
}
}).then(function (device) {
var model = new luma.Model(device, {
id: 'depth-order',
topology: 'triangle-list',
vertexCount: 18,
parameters: {
depthCompare: 'less-equal',
depthWriteEnabled: true
},
attributes: {
positions: device.createBuffer({ data: positions, usage: luma.Buffer.VERTEX }),
colors: device.createBuffer({ data: colors, usage: luma.Buffer.VERTEX })
},
bufferLayout: [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' },
{ name: 'colors', stepMode: 'vertex', format: 'float32x3' }
],
vs: [
'#version 300 es',
'in vec3 positions;',
'in vec3 colors;',
'out vec3 vColor;',
'void main() {',
' vColor = colors;',
' gl_Position = vec4(positions, 1.0);',
'}'
].join('\n'),
fs: [
'#version 300 es',
'precision highp float;',
'in vec3 vColor;',
'out vec4 fragColor;',
'void main() {',
' fragColor = vec4(vColor, 1.0);',
'}'
].join('\n')
});
var loop = new luma.AnimationLoop({
device: device,
onRender: function (props) {
var pass = props.device.beginRenderPass({
clearColor: [0.04, 0.06, 0.09, 1],
clearDepth: 1
});
model.draw(pass);
pass.end();
},
onError: function (e) { fail(e.message); }
});
loop.start();
var depthOn = true;
var cmpEl = document.getElementById('cmp');
var toggleBtn = document.getElementById('toggle');
toggleBtn.addEventListener('click', function () {
depthOn = !depthOn;
/* 'always' 会让后端关闭深度比较,深度写入仍然生效 */
model.setParameters({
depthCompare: depthOn ? 'less-equal' : 'always',
depthWriteEnabled: true
});
cmpEl.textContent = depthOn ? 'less-equal' : 'always';
toggleBtn.textContent = depthOn ? '关闭深度测试' : '开启深度测试';
loop.setNeedsRedraw('depth');
});
}).catch(function (e) {
fail(e && e.message ? e.message : String(e));
});
})();
</script>
</body>
</html>
Language: the code and this page are in English; the full tutorial and API notes for this example are in Chinese. The demo itself is the authoritative version — it runs exactly as shown.