阅读这篇文章
WebGL 永远不会是单缓冲的,这意味着您当前正在渲染的图像永远不会是当前在 Canvas 元素中显示的图像。这确保了半渲染的帧永远不会出现在浏览器的窗口中。正在渲染的图像称为 WebGL 帧缓冲区或后台缓冲区。由于 WebGL 还允许额外的屏幕外帧缓冲区,因此讨论帧缓冲区变得更加复杂,但让我们在本文中忽略这一点。当前显示的图像称为前端缓冲区。当然,后台缓冲区的内容会在某个时候被复制到前台缓冲区中——否则 WebGL 绘图将没有用户可见的效果!
我们当前渲染的图像永远不会显示在画布中,这怎么可能?
然后它说正在渲染的图像称为 webGL 帧缓冲区或后台缓冲区,显示的图像是前台缓冲区。有什么不同。有人可以在这篇文章中抛砖引玉吗?
这很简单。当你制作一个 WebGL 画布时,它有 2 个缓冲区,绘图缓冲区(也称为后台缓冲区)和显示缓冲区(也称为前台缓冲区)。
您绘制到绘图缓冲区。
如果您在画布上绘制某些内容,这意味着您调用gl.clear或gl.draw???将它们设置为渲染到画布,则浏览器会将画布标记为“需要合成”。当前事件退出后,下一次浏览器合成页面(将所有元素绘制在一起)时,它要么将绘图缓冲区复制到显示缓冲区,要么交换绘图缓冲区和显示缓冲区。
它的作用取决于浏览器和一系列其他因素。如果设置,preserveDrawingBuffer: true则它始终将绘图缓冲区复制到显示缓冲区。如果preserveDrawingBuffer为 false(默认值),则交换或复制取决于浏览器和一系列其他因素,但无论如何,何时preserveDrawingBuffer为 false WebGL 将在交换或复制后清除绘图缓冲区,以便您无法区分,因此不管它选择哪个结果都是一样的。
它有 2 个缓冲区,因为浏览器希望能够并行运行。通过这种设计,它可以随时使用显示缓冲区绘制页面,因为它包含您上次渲染的任何结果。没有它,如果您只有绘图缓冲区并再次开始绘图,并且浏览器并行地将所有元素合成在一起,那么当最终需要使用它时,它可能会从绘图缓冲区中获取您绘制的一半图像。
请注意,有 2 个缓冲区这一事实主要是您可以忽略的。从编程 WebGL 的角度来看,实际上只有 2 个结果
如果preserveDrawingBuffer为 false(默认值),则绘图缓冲区将被清除,然后浏览器会合成页面。其效果是,每次更新时都需要绘制所有内容。你不能每帧画一点。如果您想看到 3 个圆圈,则需要在同一帧中绘制 3 个圆圈。这对于大约 99% 的游戏和大约 99% 的 WebGL 应用程序来说都是正常的。在 OpenGL、DirectX、Metal、Vulkan 等中也是如此。在这些系统中编写的游戏也会在每一帧中绘制所有内容。
如果您打算使用canvas.toDataURL或canvas.toBlob或gl.readPixels或任何其他方式从 WebGL 画布获取数据,除非您在同一事件中阅读它,否则当您尝试阅读它时可能会很清楚。
换句话说,如果你这样做
function render() {
// draw stuff with WebGL
}
function renderLoop() {
render();
requestAnimationFrame(renderLoop);
}
someButton.addEventListener('click', () => {
// take screenshot
const screenshotDataURL = webglCanvas.toDataURL();
});
Run Code Online (Sandbox Code Playgroud)
屏幕截图可能会失败,因为当用户单击 时,WebGL 可能会清除绘图缓冲区someButton。
解决方案是设置preserveDrawingBuffer: true或确保在同一事件中呈现
someButton.addEventListener('click', () => {
// !!! render in the click event
render();
// take screenshot
const screenshotDataURL = webglCanvas.toDataURL();
});
Run Code Online (Sandbox Code Playgroud)类似地,如果您想绘制多个帧,例如绘制程序,那么最简单的解决方案是preserveDrawingBuffer: true在创建 WebGL 上下文时进行设置。
为了增加混淆,您提到了渲染缓冲区和帧缓冲区。这些是 WebGL 中的特定内容。
渲染缓冲区就像一个纹理,除了它与纹理不同,它不能用作着色器的输入。它只能用作输出。
帧缓冲区是纹理和渲染缓冲区的集合。当您想要渲染到纹理时,您可以将一个或多个纹理和渲染缓冲区附加到帧缓冲区。然后告诉 WebGL 你想要渲染到帧缓冲区而不是画布。完成后,您可以使用结果渲染到画布。
有关示例,请参见https://webglfundamentals.org/webgl/lessons/webgl-render-to-texture.html。
| 归档时间: |
|
| 查看次数: |
1448 次 |
| 最近记录: |