Да, WebGL трудно отлаживать, и я не уверен, что что-то сделает его намного проще. Большинство ошибок не так легко найти отладчику. Браузер уже сообщает об определенных ошибках, таких как неотрисовываемые текстуры или буферы правильного размера. Другие ошибки, однако, обычно являются математическими ошибками, логическими ошибками или ошибками данных. Например, нет простого способа пройти через шейдер 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 между кадрами.
![введите здесь описание изображения](https://i.stack.imgur.com/1PcaD.gif)
Другое дело, поможет ли это вам найти какие-либо ошибки.
обратите внимание, что если вы работаете на 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); });
}
![введите здесь описание изображения](https://i.stack.imgur.com/t2of7.gif)
Еще одна вещь, которую вы можете сделать, это использовать помощник для вызова gl.getError
после каждой функции WebGL. Вот скрипт, который вы можете использовать
<script src="https://greggman.github.io/webgl-helpers/webgl-gl-error-check.js"></script>
Вы можете либо скачать его, либо просто включить его по ссылке выше. Пример (откройте консоль 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>
18.06.2020
INVALID_ENUM
18.06.2020