在 WebGL 中调试

问题描述 投票:0回答:1

我正在学习WebGL,我可以感觉到我的速度很慢,因为我很难调试我的代码。有没有任何扩展或工具可以帮助我知道缓冲区、属性指针、矩阵等的值。

我用谷歌搜索并了解了 chrome 扩展spector.js,但这对我不起作用。我认为它应该向我显示框架或上下文,但当我单击时它什么也不显示。





当我在几秒钟后单击红色按钮时,它显示: 未检测到帧。尝试移动相机或实现 requestAnimationFrame。

webgl webgl2 webgl-extensions
1个回答
4
投票

是的,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 将不会注意到画布(将没有任何内容可供选择)。当打开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); });
  }

您可以做的另一件事是使用助手在每个 WebGL 函数之后调用

gl.getError
。这是您可以使用的脚本

<script src="https://greggman.github.io/webgl-lint/webgl-lint.js" crossorigin></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-lint/webgl-lint.js" crossorigin></script>


更新(2024)

spector 可以用作库。下载后直接调用就可以了,告诉它开始抓图

https://github.com/BabylonJS/Spector.js?tab=readme-ov-file#use-as-a-script-reference

© www.soinside.com 2019 - 2024. All rights reserved.