猿问

为什么我们应该在将一些数据放入该缓冲区之前调用 webgl.bindBuffer ?

我试图弄清楚缓冲区在 WebGL 中到底是如何工作的,但我有点卡住了。以下是我的猜测 - 请确认或否认。


const positions = new Float32Array([

 -1, 1,

 -0.5, 0,

 -0.25, 0.25,

]);


let buffer = gl.createBuffer();


gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, null);

  1. 我们通过 JS 在 RAM 上创建一个浮点数组。

  2. WebGL 直接在 GPU 上创建一个空缓冲区,并将该缓冲区的引用返回给 JS。现在变量buffer是一个指针。

  3. 将缓冲区上的指针设置为gl.ARRAY_BUFFER

  4. 现在我们将数据从 RAM复制到 GPU 缓冲区。

  5. 取消绑定缓冲区gl.ARRAY_BUFFER(但缓冲区在 GPU 上仍然可用,我们可以多次重新绑定它)。

那么为什么我们不能只调用createBuffer()withpositions而不是 usingARRAY_BUFFER作为 JS 和 GPU 之间的桥梁呢?这些只是 OpenGL API 的限制还是我们有充分的理由不这样做?如果我错了,请纠正我,但是分配已知大小的内存比分配一些内存并positions在调用后重新分配大小要快bufferData


慕婉清6462132
浏览 67回答 1
1回答

qq_遁去的一_1

因为 API 才是唯一真正的答案。许多人都同意你的观点,认为不同的 API 会更好。这是出现新 api(DirectX11/12、Vulkan、Metal、WebGPU)的原因之一但问题中的描述在技术上不正确我们通过 JS 在 RAM 上创建一个浮点数组。WebGL 创建一个代表 GPU 缓冲区的对象(GPU 上未分配任何内容)将缓冲区上的指针设置为 gl.ARRAY_BUFFER。现在我们分配一个缓冲区并将数据从 RAM 复制到 GPU 缓冲区。从 gl.ARRAY_BUFFER 取消绑定缓冲区(但该缓冲区在 GPU 上仍然可用,我们可以多次重新绑定它)。不需要第 5 步。没有理由解除缓冲区的绑定。你可以这样想。想象一下,您有一个 javascript 函数,可以将图像绘制到画布上,但图像的传递方式与示例中的缓冲区相同。这是代码class Context {  constructor(canvas) {    this.ctx = canvas.getContext('2d');  }  bindImage(img) {    this.img = img;  }  drawImage(x, y) {    this.ctx.drawImage(this.img, x, y);  }}假设您想绘制 3 张图像const ctx = new Context(someCanvas);ctx.bindImage(image1);ctx.drawImage(0, 0);ctx.bindImage(image2);ctx.drawImage(10, 10);ctx.bindImage(image3);ctx.drawImage(20, 20);会工作得很好。没有理由这样做const ctx = new Context(someCanvas);ctx.bindImage(image1);ctx.drawImage(0, 0);ctx.bindImage(null);    // not neededctx.bindImage(image2);ctx.drawImage(10, 10);ctx.bindImage(null);    // not neededctx.bindImage(image3);ctx.drawImage(20, 20);ctx.bindImage(null);    // not neededWebGL 中也是如此。有时会将 null 绑定到某些东西,例如gl.bindFramebuffer(gl.FRAMEBUFFER, null);  // start drawing to the canvas但大多数时候解除绑定只是程序员的个人喜好,而不是 API 本身所要求的
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答