是的,WebGL难以调试,我不确定是否有什么方法可以使其更容易。大多数bug并不是调试器能够轻松找到的。某些bug,例如无法渲染的纹理或正确大小的缓冲区已经被浏览器报告了。但是其他bug通常是数学bug、逻辑bug或数据bug。例如,没有简单的方法来逐步执行WebGL着色器。
无论如何,如果您想使用spector,您需要将代码结构化为spector友好型。Spector正在寻找基于requestAnimationFrame的帧。
该代码有一个名为main
的函数,看起来像这样
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("#canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
...
}
main();
main
重命名为init
,并使其可以传递gl上下文。function init(gl) {
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
...
}
然后我创建了一个看起来像这样的新main
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("#canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
const startElem = document.querySelector('button');
startElem.addEventListener('click', start, {once: true});
function start() {
// run the initialization in rAF since spector only captures inside rAF events
requestAnimationFrame(() => {
init(gl);
});
// make so more frames so spector has something to look at.
// Note: a normal webgl app would have a rAF loop: https://webglfundamentals.org/webgl/lessons/webgl-animation.html
requestAnimationFrame(() => {});
requestAnimationFrame(() => {});
requestAnimationFrame(() => {});
requestAnimationFrame(() => {});
requestAnimationFrame(() => {});
}
}
main();
我在我的html中添加了一个按钮
<button type="button">start</button>
<canvas id="canvas"></canvas>
requestAnimationFrame
中执行我们的代码,因为这是spector正在寻找的内容。它仅记录帧之间的WebGL函数。
"无论如何,它是否能帮助您发现任何错误是另一回事。
请注意,如果您使用的是Mac,Safari也内置了一个WebGL调试器,但与spector一样,它仅设计用于帧。它要求您在每个帧中绘制某些东西,因此这很有效。
" function start() {
// I'm not sure running the init code in a rAF is important in Safari but it worked
requestAnimationFrame(() => {
init(gl);
});
// by default safari tries to capture 3 frames so let's give it some frames
// Note: a normal webgl app would have a rAF loop: https://webglfundamentals.org/webgl/lessons/webgl-animation.html
requestAnimationFrame(() => { gl.clear(gl.COLOR_BUFFER_BIT); });
requestAnimationFrame(() => { gl.clear(gl.COLOR_BUFFER_BIT); });
requestAnimationFrame(() => { gl.clear(gl.COLOR_BUFFER_BIT); });
requestAnimationFrame(() => { gl.clear(gl.COLOR_BUFFER_BIT); });
requestAnimationFrame(() => { gl.clear(gl.COLOR_BUFFER_BIT); });
}
你可以使用一个助手在每个WebGL函数调用后调用gl.getError
。这是一个可以使用的脚本:
<script src="https://greggman.github.io/webgl-helpers/webgl-gl-error-check.js"></script>
const gl = document.createElement('canvas').getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.vertexAttribPointer(0, 1, gl.BYE, false, 0, 0);
<script src="https://greggman.github.io/webgl-helpers/webgl-gl-error-check.js"></script>