【性能篇】28 # Canvas、SVG与WebGL在性能上的优势与劣势

2024-01-16 11:40

本文主要是介绍【性能篇】28 # Canvas、SVG与WebGL在性能上的优势与劣势,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

说明

【跟月影学可视化】学习笔记。

可视化渲染的性能问题有哪些?

  • 渲染效率问题:指的是图形系统在绘图部分所花费的时间
  • 计算问题:指绘图之外的其他处理所花费的时间,包括图形数据的计算、正常的程序逻辑处理等等。

在浏览器上渲染动画,每一秒钟最高达到 60 帧左右。1 秒钟内完成 60 次图像的绘制,那么完成一次图像绘制的时间就是 1000/60(1 秒 =1000 毫秒),约等于 16 毫秒。

60fps(即 60 帧每秒,fps 全称是 frame per second,是帧率单位)。

达到比较流畅的动画效果的最低帧率是 24fps,相当于图形系统要在大约 42 毫秒内完成一帧图像的绘制。

影响 Canvas 渲染性能的 2 大要素

影响 Canvas 渲染性能的 2 大要素:

  • 绘制图形的数量
  • 绘制图形的大小

Google Chrome浏览器怎么开启查看帧率功能?

测试例子:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>canvas性能测试</title><style>canvas {border: 1px dashed #fa8072;}</style></head><body><canvas width="500" height="500"></canvas><script>const canvas = document.querySelector("canvas");const ctx = canvas.getContext("2d");const WIDTH = canvas.width;const HEIGHT = canvas.height;const COUNT = 500;const RADIUS = 10;function randomColor() {return `hsl(${Math.random() * 360}, 100%, 50%)`;}function drawCircle(context, radius) {const x = Math.random() * WIDTH;const y = Math.random() * HEIGHT;const fillColor = randomColor();context.fillStyle = fillColor;context.beginPath();context.arc(x, y, radius, 0, Math.PI * 2);context.fill();}function draw(context, count = 500, radius = 10) {for (let i = 0; i < count; i++) {drawCircle(context, radius);}}requestAnimationFrame(function update() {ctx.clearRect(0, 0, WIDTH, HEIGHT);draw(ctx, COUNT, RADIUS);requestAnimationFrame(update);});</script></body>
</html>

在 Canvas 上每一帧绘制 500 个半径为 10 的小圆:

在这里插入图片描述

在 Canvas 上每一帧绘制 10000 个半径为 10 的小圆:

在这里插入图片描述
在 Canvas 上每一帧绘制 10000 个半径为 100 的小圆:
在这里插入图片描述

我们可以看到随着数量的增大,半径的增大 fps 已经降到 24 以下了(还跟个人电脑的 GPU 和显卡有关)。

影响 SVG 性能的 2 大要素

影响 SVG 渲染性能的 2 大要素:

  • 绘制图形的数量
  • 绘制图形的大小

测试例子:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>svg性能测试</title><style>svg {border: 1px dashed #fa8072;}</style></head><body><svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"></svg><script>const root = document.querySelector("svg");const WIDTH = 500;const HEIGHT = 500;const COUNT = 500;const RADIUS = 10;function randomColor() {return `hsl(${Math.random() * 360}, 100%, 50%)`;}function initCircles(count = COUNT) {for (let i = 0; i < count; i++) {const circle = document.createElementNS("http://www.w3.org/2000/svg","circle");root.appendChild(circle);}return [...root.querySelectorAll("circle")];}const circles = initCircles();function drawCircle(circle, radius = 10) {const x = Math.random() * WIDTH;const y = Math.random() * HEIGHT;const fillColor = randomColor();circle.setAttribute("cx", x);circle.setAttribute("cy", y);circle.setAttribute("r", radius);circle.setAttribute("fill", fillColor);}function draw() {for (let i = 0; i < COUNT; i++) {drawCircle(circles[i], RADIUS);}requestAnimationFrame(draw);}draw();</script></body>
</html>

在 SVG 上每一帧绘制 500 个半径为 10 的小圆:

在这里插入图片描述

在 SVG 上每一帧绘制 10000 个半径为 10 的小圆:跟 canvas 对比的 SVG 的帧率就要略差一些。

在这里插入图片描述
在 SVG 上每一帧绘制 10000 个半径为 100 的小圆:跟 canvas 对比二者差距很大,因为 SVG 是浏览器 DOM 来渲染的,元素个数越多,消耗就越大。

在这里插入图片描述

SVG 与 Canvas 不同的是,图形数量增多的时候,SVG 的帧率下降会更明显,因此,一般来说,在图形数量小于 1000 时,我们可以考虑使用 SVG,当图形数量大于 1000 但不超过 3000 时,我们考虑使用 Canvas2D,当图形数量超过 3000 时,用 Canvas2D 也很难达到比较理想的帧率了,这时候,我们就要使用 WebGL 渲染。

影响 WebGL 性能的要素

WebGL 的性能主要有三点决定因素:

  • 渲染次数
  • 着色器执行的次数:图形增大,片元着色器要执行的次数就会增多,就会增加 GPU 运算的开销。
  • 着色器运算的复杂度

另外,元素越多,本身渲染耗费的内存也越多,占用内存太多,渲染效率也会下降。

WebGL 有支持的批量绘制的技术,叫做 InstancedDrawing(实例化渲染),在 OGL 库中,只需要给几何体数据传递带有 instanced 属性的顶点数据,就可以自动使用 instanced drawing 技术来批量绘制图形。

下面例子会用到:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>webgl性能测试</title><style>canvas {border: 1px dashed #fa8072;}</style></head><body><canvas width="500" height="500"></canvas><script type="module">import {Renderer,Program,Geometry,Transform,Mesh,} from "./common/lib/ogl/index.mjs";const canvas = document.querySelector("canvas");const renderer = new Renderer({canvas,antialias: true,width: 500,height: 500,});const gl = renderer.gl;gl.clearColor(1, 1, 1, 1);// 用来生成指定数量的小球的定点数据function circleGeometry(gl,radius = 0.002,count = 30000,segments = 20) {const tau = Math.PI * 2;const position = new Float32Array(segments * 2 + 2);const index = new Uint16Array(segments * 3);const id = new Uint16Array(count);for (let i = 0; i < segments; i++) {const alpha = (i / segments) * tau;position.set([radius * Math.cos(alpha), radius * Math.sin(alpha)],i * 2 + 2);}for (let i = 0; i < segments; i++) {if (i === segments - 1) {index.set([0, i + 1, 1], i * 3);} else {index.set([0, i + 1, i + 2], i * 3);}}for (let i = 0; i < count; i++) {id.set([i], i);}return new Geometry(gl, {position: {data: position,size: 2,},index: {data: index,},id: {instanced: 1, // 通过 instanced:1 的方式告诉 WebGL 这是一个批量绘制的数据size: 1,data: id,},});}const geometry = circleGeometry(gl);// 实现顶点着色器,并且在顶点着色器代码中实现随机位置和随机颜色。const vertex = `precision highp float;attribute vec2 position;attribute float id;uniform float uTime;highp float random(vec2 co) {highp float a = 12.9898;highp float b = 78.233;highp float c = 43758.5453;highp float dt= dot(co.xy ,vec2(a,b));highp float sn= mod(dt,3.14);return fract(sin(sn) * c);}//  Function from Iñigo Quiles//  https://www.shadertoy.com/view/MsS3Wcvec3 hsb2rgb(vec3 c){vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), 6.0)-3.0)-1.0, 0.0, 1.0);rgb = rgb * rgb * (3.0 - 2.0 * rgb);return c.z * mix(vec3(1.0), rgb, c.y);}varying vec3 vColor;void main() {vec2 offset = vec2(1.0 - 2.0 * random(vec2(id + uTime, 100000.0)),1.0 - 2.0 * random(vec2(id + uTime, 200000.0)));vec3 color = vec3(random(vec2(id + uTime, 300000.0)),1.0,1.0);vColor = hsb2rgb(color);gl_Position = vec4(position * 20.0 + offset, 0, 1);}`;const fragment = `precision highp float;varying vec3 vColor;void main() {gl_FragColor = vec4(vColor, 1);}`;const program = new Program(gl, {vertex,fragment,uniforms: {uTime: { value: 0 },},});const scene = new Transform();const mesh = new Mesh(gl, { geometry, program });mesh.setParent(scene);function update(t) {program.uniforms.uTime.value = t / 1000;renderer.render({ scene });requestAnimationFrame(update);}update(0);</script></body>
</html>

WebGL,绘制 30000 个小球:WebGL 渲染之所以能达到这么高的性能,是因为 WebGL 利用 GPU 并行执行的特性,无论批量绘制多少个小球,都能够同时完成计算并渲染出来。

在这里插入图片描述

这篇关于【性能篇】28 # Canvas、SVG与WebGL在性能上的优势与劣势的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/612470

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

使用Python实现PDF与SVG互转

《使用Python实现PDF与SVG互转》SVG(可缩放矢量图形)和PDF(便携式文档格式)是两种常见且广泛使用的文件格式,本文将详细介绍如何使用Python实现SVG和PDF之间的相互转... 目录使用工具使用python将SVG转换为PDF使用Python将SVG添加到现有PDF中使用Python将PD

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖