乐闻世界logo
搜索文章和话题

WebGL 1.0 和 WebGL 2.0 有什么区别?

3月6日 21:57

WebGL 版本概述

WebGL 1.0 于 2011 年发布,基于 OpenGL ES 2.0。WebGL 2.0 于 2017 年发布,基于 OpenGL ES 3.0,带来了大量新功能和性能改进。

主要区别对比

特性WebGL 1.0WebGL 2.0
基础规范OpenGL ES 2.0OpenGL ES 3.0
发布年份20112017
着色器版本GLSL ES 1.0GLSL ES 3.0
3D 纹理需要扩展原生支持
多重渲染目标(MRT)需要扩展原生支持
实例化渲染需要扩展原生支持
变换反馈不支持支持
采样器对象不支持支持
顶点数组对象(VAO)需要扩展原生支持
非2的幂次纹理有限制完全支持

着色器语言差异

WebGL 1.0 (GLSL ES 1.0)

glsl
// 顶点着色器 attribute vec3 a_position; attribute vec2 a_texCoord; uniform mat4 u_mvpMatrix; uniform sampler2D u_texture; varying vec2 v_texCoord; void main() { gl_Position = u_mvpMatrix * vec4(a_position, 1.0); v_texCoord = a_texCoord; } // 片段着色器 precision mediump float; varying vec2 v_texCoord; uniform sampler2D u_texture; void main() { gl_FragColor = texture2D(u_texture, v_texCoord); }

WebGL 2.0 (GLSL ES 3.0)

glsl
#version 300 es // 顶点着色器 in vec3 a_position; // attribute → in in vec2 a_texCoord; uniform mat4 u_mvpMatrix; out vec2 v_texCoord; // varying → out void main() { gl_Position = u_mvpMatrix * vec4(a_position, 1.0); v_texCoord = a_texCoord; } // 片段着色器 #version 300 es precision mediump float; in vec2 v_texCoord; // varying → in uniform sampler2D u_texture; out vec4 fragColor; // gl_FragColor → out 变量 void main() { fragColor = texture(u_texture, v_texCoord); // texture2D → texture }

着色器语法变化

WebGL 1.0WebGL 2.0说明
attributein顶点输入
varyingin/out顶点/片段间传递数据
gl_FragColorout 变量片段着色器输出
texture2D()texture()2D 纹理采样
textureCube()texture()立方体纹理采样
-#version 300 es版本声明(必需)

WebGL 2.0 新增功能详解

1. 3D 纹理

javascript
// WebGL 2.0 原生支持 3D 纹理 const texture3D = gl.createTexture(); gl.bindTexture(gl.TEXTURE_3D, texture3D); gl.texImage3D( gl.TEXTURE_3D, // 目标 0, // 级别 gl.RGBA, // 内部格式 width, height, depth, // 深度 0, // 边框 gl.RGBA, gl.UNSIGNED_BYTE, data );
glsl
#version 300 es uniform sampler3D u_volumeTexture; void main() { vec4 color = texture(u_volumeTexture, vec3(x, y, z)); }

2. 多重渲染目标(MRT)

javascript
// 创建帧缓冲区,绑定多个颜色附件 const framebuffer = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); // 附加多个纹理 const textures = []; for (let i = 0; i < 4; i++) { const texture = gl.createTexture(); // ... 配置纹理 gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, // COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, ... gl.TEXTURE_2D, texture, 0 ); textures.push(texture); } // 指定绘制到哪些附件 gl.drawBuffers([ gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3 ]);
glsl
#version 300 es layout(location = 0) out vec4 color0; layout(location = 1) out vec4 color1; layout(location = 2) out vec4 color2; layout(location = 3) out vec4 color3; void main() { color0 = vec4(1.0, 0.0, 0.0, 1.0); color1 = vec4(0.0, 1.0, 0.0, 1.0); color2 = vec4(0.0, 0.0, 1.0, 1.0); color3 = vec4(1.0, 1.0, 1.0, 1.0); }

3. 实例化渲染(Instanced Rendering)

javascript
// WebGL 2.0 原生支持 // 绘制 1000 个实例,每个实例使用不同的变换 const instanceCount = 1000; gl.drawArraysInstanced(gl.TRIANGLES, 0, vertexCount, instanceCount); // 或使用索引绘制 gl.drawElementsInstanced(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0, instanceCount);
glsl
#version 300 es in vec3 a_position; in mat4 a_instanceMatrix; // 实例化矩阵 void main() { gl_Position = u_projectionMatrix * u_viewMatrix * a_instanceMatrix * vec4(a_position, 1.0); }

4. 变换反馈(Transform Feedback)

javascript
// 创建变换反馈对象 const transformFeedback = gl.createTransformFeedback(); // 设置顶点着色器输出 const vertexShaderSource = `#version 300 es in vec3 a_position; out vec3 v_newPosition; // 变换后的位置 void main() { v_newPosition = a_position * 2.0; // 某种变换 } `; // 配置变换反馈 const program = gl.createProgram(); // ... 编译链接着色器 gl.transformFeedbackVaryings( program, ['v_newPosition'], // 要捕获的输出变量 gl.SEPARATE_ATTRIBS // 或 INTERLEAVED_ATTRIBS ); // 执行变换反馈 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback); gl.beginTransformFeedback(gl.POINTS); gl.drawArrays(gl.POINTS, 0, count); gl.endTransformFeedback();

5. 采样器对象(Sampler Objects)

javascript
// 将纹理参数从纹理对象分离 const sampler = gl.createSampler(); // 配置采样器参数 gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); // 绑定采样器到纹理单元 gl.bindSampler(0, sampler); // 绑定到纹理单元 0

6. 顶点数组对象(VAO)原生支持

javascript
// WebGL 2.0 原生支持,无需扩展 const vao = gl.createVertexArray(); gl.bindVertexArray(vao); // 配置顶点属性(存储在 VAO 中) gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); gl.bindVertexArray(null); // 绘制时只需绑定 VAO gl.bindVertexArray(vao); gl.drawArrays(gl.TRIANGLES, 0, count);

新纹理功能

非2的幂次纹理完整支持

javascript
// WebGL 2.0 中,非2的幂次纹理支持所有功能 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.generateMipmap(gl.TEXTURE_2D); // 也支持 mipmap

纹理数组

javascript
const textureArray = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D_ARRAY, textureArray); gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, width, height, layerCount, // 层数 0, gl.RGBA, gl.UNSIGNED_BYTE, data );

如何检测 WebGL 2.0 支持

javascript
function getWebGLContext(canvas) { // 优先尝试 WebGL 2.0 let gl = canvas.getContext('webgl2'); if (gl) { console.log('Using WebGL 2.0'); return gl; } // 回退到 WebGL 1.0 gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (gl) { console.log('Using WebGL 1.0'); return gl; } console.error('WebGL not supported'); return null; }

浏览器支持情况

浏览器WebGL 1.0WebGL 2.0
Chrome✓ (56+)
Firefox✓ (51+)
Safari✓ (15+)
Edge✓ (79+)
IE 11

迁移建议

  1. 渐进增强:先检测 WebGL 2.0 支持,不支持时回退到 1.0
  2. 着色器版本:为两个版本准备不同的着色器代码
  3. 功能检测:使用特定功能前检查是否可用
  4. 性能考虑:WebGL 2.0 功能更强大,但 1.0 兼容性更好
标签:WebGL