【问题标题】:why webgl canvas context use much more memory than 2d canvas?为什么 webgl 画布上下文比 2d 画布使用更多的内存?
【发布时间】:2020-11-04 03:04:38
【问题描述】:

1024x1024 2d 画布可能使用大约 1024 * 1024 * 4 = 4M 内存,但 webGL 上下文使用至少 5-10 倍以上的内存。

<!DOCTYPE html>
<html>
    <body>
    
        <div style="display:inline-block ;overflow: hidden;width: 512px;height: 512px;">
            <canvas id="canvas" width="1024" height="1024" style="border: red 1px solid;transform: scale(0.5); transform-origin: 0 0;">old version need update</canvas>
        </div>
    </body>

    <script>
        var ctx = window.document.getElementById("canvas").getContext("webgl")
        var gl = canvas.getContext("experimental-webgl");

    </script>

</html>

【问题讨论】:

    标签: canvas webgl


    【解决方案1】:

    可能有多种原因

    默认情况下,webgl 画布是抗锯齿的。

    浏览器选择金额但检查

    const gl = document.createElement('canvas').getContext('webgl');
    const samples = gl.getParameter(gl.SAMPLES) || 1;
    console.log(`samples is ${samples} so this canvas is actually ${gl.canvas.width * samples} x ${gl.canvas.height * samples} pixels big internally`);

    在我的机器上,300x150 的画布实际上是 1200x600,因为那是 how a GPU's built in antialiasing works

    创建上下文时可以通过传入antialias: false来关闭抗锯齿

    const gl = document.createElement('canvas').getContext('webgl', {
      antialias: false,
    });
    const samples = gl.getParameter(gl.SAMPLES) || 1;
    console.log(`samples is ${samples} so this canvas is actually ${gl.canvas.width * samples} x ${gl.canvas.height * samples} pixels big internally`);

    WebGL 是双缓冲的

    所以总会分配至少 2 个缓冲区,绘图缓冲区(渲染到的缓冲区)和用于渲染页面的副本。因此,即使关闭抗锯齿,也会有 2 个缓冲区,而 2D 画布可能只有 1 个(这取决于浏览器对 2D 画布的作用)

    WebGL 需要 GL 上下文和相关支持

    WebGL 在浏览器内部创建某种上下文来跟踪所有状态。该状态是每个 WebGL 上下文。换句话说,如果您创建 2 个 WebGL 上下文,浏览器需要跟踪 2 组 WebGL 状态。在 Chrome 中,它包括命令缓冲区和其他缓冲区,用于将命令和数据从运行网页的进程传输到与 GPU 通信的进程。这本身可以是2-4兆。另一方面,Canvas 2D 最有可能分配该信息一次并在所有画布上共享它。在查看内存使用情况时甚至可能没有考虑到它。

    【讨论】:

    • 非常感谢,我没有意识到 webgl 使用 ssaa 来抗锯齿。在我的机器上,参数是 8。
    • 开发者可以控制内置的 webgl 抗锯齿参数吗?关闭 ssaa 样本 8 太糟糕了,我可以设置小样本参数吗,或者我必须自己使用 msaa 或其他抗锯齿技术进行抗锯齿。
    • 您不能将画布的抗锯齿设置为 false(关闭)或 true(让浏览器决定)。您可以通过帧缓冲区渲染到纹理,并在将其渲染到画布时对其进行任何处理。您还可以使画布比显示的更大,并在合成时获得双线性过滤。在 WebGL2 中,您可以创建自己的多样本渲染缓冲区,但在 WebGL1 中则不行
    猜你喜欢
    • 1970-01-01
    • 2020-11-17
    • 2019-05-07
    • 2019-03-20
    • 2012-01-09
    • 1970-01-01
    • 2011-04-22
    • 2016-01-27
    • 2016-12-25
    相关资源
    最近更新 更多