当前位置: 首页 > news >正文

WebGL3(WebGL or WebGPU?)

1 WebGL介绍

WebGL(Web Graphics Library)是一种基于OpenGL ES的JavaScript API,用于在网页浏览器中实现高性能的3D图形渲染,无需安装额外插件。它通过着色器(Shader)编程直接调用GPU能力,支持复杂的3D场景、物理模拟和实时渲染效果。

WebGL完全集成于HTML5 Canvas,可与JavaScript、CSS3和Web API无缝协作,广泛应用于游戏开发、数据可视化、虚拟/增强现实(VR/AR)、科学模拟和交互式艺术等领域,为现代Web应用带来沉浸式视觉体验。主流浏览器(如Chrome、Firefox、Safari和Edge)均提供支持,是构建跨平台3D网页内容的标准技术。

要验证当前是否支持webgl。直接打开:https://get.webgl.org/

关于图形的部分,直接可以在网页查看。chrome://gpu/

我的输入如下:

官方API手册:WebGL 2.0 Specification

另一个API手册:WebGL: 2D and 3D graphics for the web - Web APIs | MDN

单页速查手册:https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf 

互动学习教程:WebGL2 理论基础

2 WebGL例子

2.1 三角形

代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebGL Triangle</title><style>body { margin: 0; overflow: hidden; }canvas { display: block; }</style>
</head>
<body><canvas id="glcanvas" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl');const vsSource = `attribute vec2 a_position;void main() {gl_Position = vec4(a_position, 0.0, 1.0);}
`;
const fsSource = `void main() {gl_FragColor = vec4(1, 0, 0, 1);  // 红色}
`;// 编译着色器
function compileShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);return shader;
}const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fsSource);const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);// 设置顶点数据
const vertices = new Float32Array([0, 1,-1, -1,1, -1
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 启用属性
gl.useProgram(program);
const aPosition = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(aPosition);
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);// 绘制
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script></body>
</html>    

 效果

2.2 渐变色

代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebGL Triangle</title><style>body { margin: 0; overflow: hidden; }canvas { display: block; }</style>
</head>
<body><canvas id="glcanvas" width="400" height="400"></canvas><canvas id="glcanvas" width="400" height="400"></canvas><script>const canvas = document.getElementById('glcanvas');const gl = canvas.getContext('webgl');const vs = `attribute vec2 a_position;varying vec2 v_pos;void main() {v_pos = a_position;gl_Position = vec4(a_position, 0, 1);}`;const fs = `precision mediump float;varying vec2 v_pos;void main() {gl_FragColor = vec4(v_pos * 0.5 + 0.5, 1.0, 1.0);  // x y 映射到 RGB}`;const compile = (type, src) => {const s = gl.createShader(type);gl.shaderSource(s, src);gl.compileShader(s);return s;};const prog = gl.createProgram();gl.attachShader(prog, compile(gl.VERTEX_SHADER, vs));gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, fs));gl.linkProgram(prog);gl.useProgram(prog);const quad = new Float32Array([-1, -1, 1, -1, -1, 1,-1, 1, 1, -1, 1, 1]);const buf = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, buf);gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);const pos = gl.getAttribLocation(prog, 'a_position');gl.enableVertexAttribArray(pos);gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);gl.drawArrays(gl.TRIANGLES, 0, 6);</script></body>
</html>    

效果

2.3 旋转立方体

代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebGL Triangle</title><style>body { margin: 0; overflow: hidden; }canvas { display: block; }</style>
</head>
<body><script src="https://cdn.jsdelivr.net/npm/three@0.152.2/build/three.min.js"></script>
<canvas id="canvas"></canvas>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({canvas: document.getElementById("canvas")});
renderer.setSize(400, 400);const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: true});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);camera.position.z = 3;function animate() {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);
}
animate();
</script></body>
</html>    

效果

3 WebGL的实现

其实就是ANGLE,项目主页:https://github.com/google/angle

这个其实也是谷歌维护的项目,本质上,就是就是提供了一套opengl es的接口。为什么不用原生的opengl es呢?据说原因有几个,一个是opengl es的驱动一般是原厂提供,质量参差不齐。第二个是直接让webgl操作gles给的权限太大,相当于直接可以操作硬件了,最后有个中间层,可以跨Vulkan、D3D、Metal,相当于手机,苹果,PC全包,提供的兼容性更好。

对于谷歌安卓的原生应用,考虑到性能,还是直接使用的opengl es,但是Flutter现在也都是使用ANGLE了。

在windows下的库是libEGL_angle.so。

策略一览:

浏览器是否默认用 ANGLE特殊说明
Chrome(Windows/Android)✅ 默认用 ANGLE后端通常是 Vulkan 或 D3D11/12
Edge✅ 默认用 ANGLE同 Chrome
ChromeOS✅ 用 ANGLE为稳定性优化
Firefox❌ 默认直接调用 GLES(Linux/Android)或 OpenGL(桌面)可选用 ANGLE(WebRender)
Safari❌ 不用 ANGLE使用系统 Metal/OpenGL 实现(macOS/iOS)
Chromium Embedded Framework (CEF)✅ 可配置是否用 ANGLE大多默认开启

转换的内容如下:

  • Windows 平台默认将 OpenGL ES → Direct3D 11

  • macOS 平台:OpenGL ES → Metal

  • Linux 或特定构建:OpenGL ES → Vulkan(或原生 OpenGL)

以glDrawArrays()为例,在windows下的ANGLE调用的就是Direct3D,过程如下:

[ WebGL JS ] 
   ↓
[ glDrawArrays(...) ]  ← 用户 JS 层
   ↓
[ libGLESv2/libANGLE ] ← ANGLE OpenGL ES API 接口层
   ↓
[ Context::drawArrays(...) ] ← 通用 ANGLE 调度
   ↓
[ RendererD3D::drawArrays(...) ] ← 后端实现(如 D3D11)
   ↓
[ ID3D11DeviceContext::Draw(...) ] ← GPU 驱动调用
 

4 WebGPU

在上面说过,WebGL是基于ANGLE,而ANGLE是opengl es接口。那么就有一个问题,那就是opengl es是opengl的简化版,天生性能不足。

特性OpenGLOpenGL ES
定位桌面/工作站高性能图形(PC、Mac)嵌入式/移动设备(手机、平板、车载系统)
复杂度功能全面,API 较庞大精简版,移除冗余功能,保留核心渲染能力
标准组织Khronos GroupKhronos Group
派生关系OpenGL ES 是 OpenGL 的子集基于 OpenGL 裁剪,专为低功耗优化

具体限制如下:

类型是否支持说明
计算着色器(Compute Shader)❌ 不支持无法做 GPGPU 计算
几何着色器(Geometry Shader)❌ 不支持不能动态生成图元
高级渲染管线❌ 不支持无 Tessellation
延迟渲染(Deferred Shading)✅ 可模拟可用 FBO + MRT 实现
实时阴影✅ 可模拟用 shadow map 技术
后处理特效✅ 可实现用多个 FBO + shader 实现

为了提供更高的性能和功能。所以,在之后的规范中,又搞出来了WebGPU,模式和上面大差不差,规范地址:WebGPU

特性WebGLWebGPU
基于 APIOpenGL ES(老旧)Vulkan / D3D12 / Metal(现代)
浏览器实现方式通常通过 ANGLE 转译为 Vulkan/D3D/Metal直接调用系统的底层图形 API
ANGLE 依赖✅ 是核心依赖❌ 默认不依赖
性能开销较高(多一层抽象)更低,更靠近底层硬件
现代 GPU 特性支持弱,受 GLES 限制强,支持计算着色器、并行指令、精细控制等

 谷歌也提供了一个叫做Dawn的中间层。 地址是:https://github.com/google/dawn

 5 WebGPU的例子

自己看吧,比我搞的简单例子强多了。

three.js examples

WebGPU Samples

6 原生/WebGL/WebGPU性能比较

数据来自deepseek

测试场景

一个包含大量动态物体的3D场景:

  • 100,000个旋转的立方体

  • 每帧更新所有物体的变换矩阵

  • 使用相同的着色器程序

  • 相同的渲染质量设置

在配备NVIDIA GTX 1080的测试机器上,渲染100,000个立方体的帧率(FPS):

技术平均FPS特点
原生OpenGL45 FPS直接硬件访问,但每个物体单独绘制调用
原生Vulkan120 FPS多线程命令缓冲,更低的驱动开销
WebGL 2.012 FPS高绘制调用开销,JavaScript瓶颈
WebGPU85 FPS接近原生性能,支持多线程和计算着色器

 从这个测试来看,WebGPU比WebGL提升够大的,差不多7倍了。

Vulkan比OpenGL提升也够大的,差不多3倍。

WebGPU是OpenGL两倍也是没想到。。。

相关文章:

  • 云手机是什么?哪个云手机便宜好用,掌派云手机流畅不卡顿
  • 如何解答一个C++编程题目
  • Docker 一键部署倒计时页面:Easy Countdown全设备通用
  • 西门子PLC S7-200接编码器开发
  • 数据库故障排查指南技术文章
  • Linux `date` 命令深度解析与高阶应用指南
  • numpy执行无缘无故崩溃 没有报错
  • 13软件测试用例设计方法-场景法
  • Baklib知识中台构建实战
  • Python 内存管理机制详解:从分配到回收的全流程剖析
  • Ansible常用Ad-Hoc 命令
  • 动态规划-53.最大子数组和-力扣(LeetCode)
  • CentOS 7.6 + Docker:搭建后端常用的开发环境
  • springboot3 configuration
  • 软件质量保证与测试实验
  • 【计算机CPU架构】x86架构简介
  • <collection> 标签:用于定义 一对多关系 的映射规则
  • 【Python 集合 Set 】全面学习指南
  • 可转债双低轮动策略
  • c/c++怎样编写可变参数函数.
  • Win8系统里dw如何做动态网站/网站收录查询入口
  • 换域名影响网站不/微营销系统
  • 网站seo快速/荆门网络推广
  • 网站制作 服务/青岛seo网站建设公司
  • 咖啡网站开发/网站制作论文
  • 小程序可做网站吗/旺道seo工具