在WebGL中进行调试

3

我正在学习WebGL,但是由于很难调试代码,所以感觉速度很慢。有没有什么扩展或工具可以帮助我了解缓冲区、属性指针、矩阵等的值。

我搜索了一下,了解到了Chrome扩展程序Spector.js,但是它对我没有用。我认为它应该显示帧或上下文,但当我点击时什么都没有显示。



enter image description here



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

1个回答

3

是的,WebGL难以调试,我不确定是否有什么方法可以使其更容易。大多数bug并不是调试器能够轻松找到的。某些bug,例如无法渲染的纹理或正确大小的缓冲区已经被浏览器报告了。但是其他bug通常是数学bug、逻辑bug或数据bug。例如,没有简单的方法来逐步执行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函数。

enter image description here

"

无论如何,它是否能帮助您发现任何错误是另一回事。

请注意,如果您使用的是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); });
  }

enter image description here

你可以使用一个助手在每个WebGL函数调用后调用gl.getError。这是一个可以使用的脚本:

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


1
如果您使用底部提到的脚本,它将在错误发生的地方停止。 - gman
请问为什么会有多个没有回调函数的requestAnimationFrame?我不太理解。是的,感谢您创建这个伟大的东西,这是一个很棒的工具和非常棒的。 - pravin poudel
我已经指导过你了。我给了你一个链接代码,并附上了确切的操作说明,让你能够使其正常工作。请按照说明进行操作。 - gman
我没有点击按钮来触发事件,这会对此有影响吗? - pravin poudel
非常感谢您提供的WebGL错误检查脚本。它帮助我在几分钟内找出了所有的错误。 - Elouarn Laine
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接