Да, WebGL сложно отлаживать, и я не уверен, что что-то сделает его намного проще. Большинство ошибок не так легко найти отладчику. Браузер уже сообщает о некоторых ошибках, таких как невозможность визуализации текстур или буферов правильного размера. Другие ошибки обычно представляют собой математические ошибки, ошибки logi c или ошибки данных. Например, не существует простого способа пройти через шейдер 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>
Код такой, потому что нам нужно сначала получить контекст webgl, иначе spector не заметит холст (нечего будет выбирать ). После этого включаем спектор, и только после этого нажимаем кнопку запуска, чтобы запустить наш код. Нам нужно выполнить наш код в requestAnimationFrame
, потому что это именно то, что ищет spector. Он записывает только функции WebGL между кадрами.
Whether or not it will help you find any bugs though is another matter.
note that, if you are on Mac, Safari also has a WebGL debugger built in but just like spector it's only designed for frames. It requires you to draw something each frame so this worked
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); });
}
Another thing you can do is use a helper to call gl.getError
after every WebGL function. Here's a script you can use
Вы можете скачать или просто включите его по ссылке выше. Пример (откройте консоль javascript, чтобы увидеть ошибку)
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>