Skip to content

WebGL - 上下文

任何 WebGL 应用程序的第一步都是获取 WebGL Rendering Context(WebGL 渲染上下文)。这个 JavaScript 对象是通往 WebGL API 的门户,提供了配置图形管线状态、管理 GPU 资源(缓冲区、纹理、着色器)和发出绘制命令所需的所有方法。

流程包括:

  • 创建一个 HTML <canvas> 元素。
  • 在 JavaScript 中获取该元素的引用。
  • 从 canvas 元素请求 WebGL 上下文。

WebGL 渲染到 HTML <canvas> 元素中。你可以在 HTML 结构中像定义其他元素一样定义它:

  • 使用 <canvas> 标签。
  • 分配一个唯一的 id 属性,以便使用 JavaScript 轻松选择它。
  • 可选地设置 width 和 height 属性来定义 canvas 的分辨率(绘制缓冲区大小)。CSS 可以用于样式(如边框)和缩放其显示大小,但 width 和 height 属性控制实际的渲染目标尺寸。

这段 HTML 设置了一个带有 ID 和特定尺寸的 canvas,并添加了一个简单的边框以方便查看。

<!DOCTYPE html>
<html>
<head>
<title>WebGL Canvas Setup</title>
<style>
/* Style the canvas element itself */
#myWebGLCanvas {
border: 1px solid blue; /* 设置蓝色边框 */
width: 600px; /* Display size (can differ from render size) (显示尺寸,可以与渲染尺寸不同) */
height: 400px;
}
</style>
</head>
<body>
<!-- The canvas element where WebGL will draw -->
<!-- width/height attributes define the drawing buffer size -->
<canvas id="myWebGLCanvas" width="600" height="400"> <!-- WebGL 将在此处绘制的 canvas 元素 -->
您的浏览器似乎不支持 HTML canvas 元素。
</canvas>
<script>
// JavaScript to get the context will go here
// 获取上下文的 JavaScript 代码将放在这里
</script>
</body>
</html>

在浏览器中打开此 HTML 文件会显示一个蓝色边框的矩形。

使用标准的 Document Object Model (DOM,文档对象模型) 方法 document.getElementById(),通过你分配的 ID 获取 canvas 元素的引用。

const canvas = document.getElementById('myWebGLCanvas');
if (!canvas) {
console.error('Could not find the canvas element!'); // 找不到 canvas 元素!
} else {
// Proceed to get the context...
// 继续获取上下文...
}

获取 canvas 元素引用后,调用其 getContext() 方法。此方法尝试创建并返回请求的渲染上下文。

语法:

const context = canvas.getContext(contextType, contextAttributes);
  • contextType:一个字符串,指定所需的上下文类型。对于 WebGL:
    • 'webgl':请求 WebGL 1.0 上下文(基于 OpenGL ES 2.0)。这是标准标识符。
    • 'webgl2':请求 WebGL 2.0 上下文(基于 OpenGL ES 3.0)。提供更多功能,但需要较新的硬件/驱动。
    • 'experimental-webgl':WebGL 开发期间使用的旧版标识符。一些旧浏览器可能只支持此项。最好优先尝试 'webgl' 或 'webgl2'。
  • contextAttributes (可选):一个包含上下文创建选项的对象(见下文)。

以下代码片段尝试获取 WebGL 1.0 上下文。检查返回的值是否为 null 至关重要,它表示失败(浏览器不支持 WebGL,或上下文创建失败)。

const canvas = document.getElementById('myWebGLCanvas');
let gl = null; // Use 'let' as it might be reassigned for fallback (使用 'let',因为它可能会在备用方案中重新赋值)
try {
// Try getting the standard WebGL 1.0 context
gl = canvas.getContext('webgl'); // 尝试获取标准的 WebGL 1.0 上下文
} catch (e) {
console.error('Error creating WebGL context:', e); // 创建 WebGL 上下文时出错:
}
if (!gl) {
// Fallback for older browsers
console.warn('Standard WebGL context not available, trying experimental-webgl.'); // 标准 WebGL 上下文不可用,尝试 experimental-webgl。
try {
gl = canvas.getContext('experimental-webgl');
} catch (e) {
console.error('Error creating experimental-webgl context:', e); // 创建 experimental-webgl 上下文时出错:
}
}
// Final check
if (!gl) {
alert('Unable to initialize WebGL. Your browser or graphics card may not support it.'); // 无法初始化 WebGL。您的浏览器或显卡可能不支持它。
// Handle the error appropriately - maybe display a message to the user
// 适当处理错误 - 可以向用户显示一条消息
} else {
console.log('WebGL context obtained successfully!'); // 成功获取 WebGL 上下文!
// Start your WebGL application logic here...
// 在这里开始你的 WebGL 应用逻辑...
}

如果成功,变量 gl(惯用名称)现在持有 WebGLRenderingContext 对象。

WebGL 上下文属性(Context Attributes)

Section titled “WebGL 上下文属性(Context Attributes)”

可选的 contextAttributes 对象允许你在创建上下文时请求绘制缓冲区的特定功能或配置。常用属性包括:

属性描述默认值
alpha布尔值。如果为 true,则绘制缓冲区具有 alpha 通道。如果你不需要透明度并希望获得潜在的性能提升,请设置为 false。true
depth布尔值。如果为 true,则绘制缓冲区包含深度缓冲区(至少 16 位)。对于 3D 渲染至关重要。true
stencil布尔值。如果为 true,则绘制缓冲区包含模板缓冲区(至少 8 位)。用于高级技术,如遮罩。false
antialias布尔值。如果为 true,则请求浏览器执行抗锯齿(平滑锯齿状边缘)。性能影响各异;支持和质量取决于浏览器/GPU。true(但实际行为可能不同)
premultipliedAlpha布尔值。如果为 true,则绘制缓冲区中的颜色通道被假定为已预乘以 alpha 通道。影响透明度的处理方式,尤其是在将 canvas 与页面其余部分合成时。true
preserveDrawingBuffer布尔值。如果为 true,则在渲染和合成后保留绘制缓冲区的内容。如果为 false(默认),则缓冲区内容可能会被清除或变得不确定。设置为 true 对于绘制轨迹或截图等效果很有用,但通常会带来显著的性能成本。false
powerPreference一个提示('default'、'low-power'、'high-performance'),用于在具有多个 GPU(如集成显卡 + 独立显卡)的系统上向浏览器提示 GPU 选择。'default'
failIfMajorPerformanceCaveat布尔值。如果为 true,则如果实现预计性能会较差(例如,使用软件渲染),上下文创建将失败。false

请求一个不带抗锯齿和带模板缓冲区的上下文:

const canvas = document.getElementById('myWebGLCanvas');
const contextOptions = {
antialias: false,
stencil: true,
powerPreference: 'high-performance' // Request high performance GPU if available (如果可用,请求高性能 GPU)
};
let gl = canvas.getContext('webgl', contextOptions);
if (!gl) {
// Handle error or try fallbacks...
// 处理错误或尝试备用方案...
}

getContext() 返回的对象(通常存储在 gl 中)是 WebGLRenderingContext(用于 WebGL 1)或 WebGL2RenderingContext(用于 WebGL 2)的一个实例。此接口提供:

  • 方法(Methods): 所有 WebGL 操作的函数(例如,gl.clear()、gl.createBuffer()、gl.drawArrays()、gl.uniformMatrix4fv() 等)。
  • 常量(Constants): 用作方法参数的预定义值(例如,gl.TRIANGLES、gl.COLOR_BUFFER_BIT、gl.FLOAT)。
  • 属性(Attributes): 提供关于上下文和绘制缓冲区信息的属性。
序号属性描述
1canvas对创建此上下文的 HTMLCanvasElement 的只读引用。
2drawingBufferWidth只读。绘制缓冲区的实际宽度(像素)。这与 canvas 的 width 属性匹配。
3drawingBufferHeight只读。绘制缓冲区的实际高度(像素)。这与 canvas 的 height 属性匹配。

成功获取 WebGL 渲染上下文后,你就可以开始使用其方法和常量来构建你的图形应用程序了。