Хобрук: Ваш путь к мастерству в программировании

Отладка в WebGL

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

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



введите здесь описание изображения



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


Ответы:


1

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

введите здесь описание изображения

Другое дело, поможет ли это вам найти какие-либо ошибки.

обратите внимание, что если вы работаете на 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); });
  }

введите здесь описание изображения

Еще одна вещь, которую вы можете сделать, это использовать помощник для вызова 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
  • Спасибо за то, что вы в Интернете и помогаете таким, как я, кто очень старается учиться !!! Я потратил впустую пару часов только для того, чтобы обнаружить, что тип vertexattribpointer был gl.BYE, а не gl.BYTE. Я перечитывал эту строчку несколько раз, но мой глаз не мог ее уловить. Меня так раздражает, что браузер не показал мне никакой ошибки!!! 18.06.2020
  • Странно, у вас должна была быть ошибка INVALID_ENUM 18.06.2020
  • Нет, но было предупреждение, но не ошибка, поэтому я не мог найти, откуда берется ошибка. 18.06.2020
  • хорошо, если вы используете скрипт, упомянутый внизу, он остановится там, где произошла ошибка. 18.06.2020
  • не могли бы вы сказать мне, почему существует несколько requestAnimationFrame без обратного вызова. Я не мог этого понять. Да, спасибо за создание этого замечательного материала, это отличный инструмент и потрясающий. 18.06.2020
  • Просто потому, что некоторые из этих инструментов пытаются захватить более 1 кадра, я просто скопировал и вставил линии, чтобы сделать больше кадров. Большинство приложений webgl рендерятся непрерывно, поэтому в этом нет необходимости, за исключением случаев, когда вы хотите захватить первый кадр, вам все равно нужно сделать основную/инициализирующую вещь и инициализировать в requestAnimationFrame, но вам не нужны остальные 18.06.2020
  • Я написал requestAnimationFrame() с инициализацией в качестве обратного вызова внутри main, но это не сработало. Я вызвал requestAnimationFrame внутри функции инициализации в конце, чтобы вызвать ее рекурсивно. Мне любопытно, если это не эффективный способ сделать это. Просто вызов requestAnimationFrame(function(){init(gl)}); не дал требуемого вывода с помощью Spector.js, но сработал рекурсивный вызов. Не могли бы вы помочь мне в этом, потому что, как вы сказали, Spector ищет код только внутри requestAnimationFrame, поэтому я могу позвонить только один раз. 18.06.2020
  • Я вел тебя. Я дал вам код ссылки с точными инструкциями, чтобы заставить его работать. Следуйте за ними. 18.06.2020
  • Затем вы что-то изменили, потому что это работает. Так что выясните, что вы сделали по-другому, или задайте новый вопрос и опубликуйте весь свой неработающий код. 18.06.2020
  • у меня нет кнопки нажатия для запуска события, это имеет значение? 18.06.2020
  • Да, это имеет значение! Это необходимо, потому что spector не запускается, пока вы его не включите, поэтому он не будет захватывать первый кадр, в котором происходит вся ваша инициализация, если только вы не инициализируете его до тех пор, пока не включите его. Вот почему есть кнопка запуска. Таким образом, вы можете загрузить страницу, затем включить spector, а затем нажать «Пуск». 18.06.2020
  • Спасибо, это сработало как шарм, и еще раз спасибо за то, что вы были добры и помогли мне. 19.06.2020
  • Большое спасибо за скрипт проверки ошибок webgl. Это помогло мне выявить все мои ошибки за считанные минуты. 25.04.2021
  • Новые материалы

    Что такое структура данных?
    Структура данных хранит и извлекает данные. Все, что обеспечивает эти две функции, является структурой данных . Период. Вы можете пропустить оставшуюся часть статьи, если ответ..

    мои январские чтения по программированию
    Эрик Эллиот Программирование приложения JavaScript Эл Свейгарт «Автоматизируйте скучные вещи с помощью Python» Прогрессивное веб-приложение Google..

    Создание ассоциаций секвелизации с помощью инструмента командной строки Sequelize
    Sequelize - популярный, простой в использовании инструмент объектно-реляционного сопоставления (ORM) JavaScript, который работает с базами данных SQL. Довольно просто начать новый проект с..

    Искусственный интеллект в юридической отрасли - пример прогнозирования судебных решений с помощью глубокого обучения
    На протяжении всей истории люди полагались на суды, присяжных, королей и королев в отправлении правосудия. Сегодня способность судов обеспечивать справедливое и быстрое правосудие для своих..

    Введение в машинное обучение для обнаружения аномалий (часть 1)
    Тщательно созданный, тщательно спроектированный ресурс для специалистов по данным. Часть 1 Главы 03 из Руководства по машинному обучению для обнаружения аномалий Внимание! Прежде чем вы..

    Начало работы с Pulumi в Digital Ocean
    Цифровой океан (ДО) — отличная альтернатива многим другим поставщикам облачных услуг. DO предоставляет простой и понятный пользовательский интерфейс, упрощающий управление инфраструктурой и..

    #Day68 из #100days_of_coding
    Вчера был мой 68-й день кодинга. я решил один вопрос Проблема: Разбить двоичную строку на подстроки с равным количеством нулей и единиц Дана двоичная строка str длины N . Задача состоит..