Отладка в WebGL - PullRequest
       103

Отладка в WebGL

0 голосов
/ 18 июня 2020

Я изучаю WebGL и чувствую, что моя скорость настолько низкая, потому что мне трудно отлаживать свой код. Есть ли какое-либо расширение или инструмент, с помощью которого я могу узнать значение буфера, атрибута, матриц и т. Д. c.

Я погуглил и узнал о chrome extension spector. js, но это не работает со мной. Я думаю, он должен показывать мне кадры или контекст, но когда я нажимаю, он ничего не показывает. enter image description here

Когда я нажимаю красную кнопку через несколько секунд, отображается: Кадры не обнаружены. Попробуйте переместить камеру или реализовать requestAnimationFrame.

1 Ответ

1 голос
/ 18 июня 2020

Да, 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 между кадрами.

enter image description here

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

enter image description here

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>
...