【WebGL系列-01】获取WebGL上下文

获取WebGL上下文

获取上下文

WebGL上下文是从<canvas>标签中获取到的,通过canvas对象的getContext()函数可以获取WebGLRenderingContext

跟据参数的不同,getContext()函数可以获取不同种类的渲染上下文。

接口

canvas.getContext(contextType: String, contextAttributes ?: Object)

  • contextType:

    • '2d':建立一个CanvasRenderingContext2D二维渲染上下文
    • 'webgl''experimental-webgl':创建一个WebGLRenderingContext三维上下文对象,只在实现WebGL1的浏览器上可用
    • 'webgl2''experimental-webgl2':创建一个WebGL2RenderingContext三维渲染上下文对象,只在实现WebGL2的浏览器上可用
    • 'bitmaprenderer':创建一个只提供将canvas内容替换为指定ImageBitmap功能的ImageBitmapRenderingContext
  • contextAttributes:

    • contextType2d时:

      • alpha:boolean,表明canvas包含一个alpha通道。如果设置为false,浏览器默认canvas背景总是不透明的,可加速绘制透明物体
      • willReadFrequently (Gecko only):boolean,表示是否有重复读取计划。经常使用getImageData()会导致软件使用2D canvas并节省内存,适用于存在属性gfx.canvas.willReadFrequently的环境
      • storage (Blink only):string,表示使用哪种方式存储,默认为"presistent"持久性存储
    • 当使用webgl上下文时:

      • alpha:boolean,表明canvas包含一个alpha缓冲区
      • antialias:boolean,表明是否开启抗锯齿
      • depth:boolean,表明绘制缓冲区包含一个深度至少为16位的缓冲区
      • failIfMajorPerformanceCaveat:表明在一个系统性能低的环境是否创建该上下文的boolean值
      • powerPreference:指示浏览器在运行webgl上下文时使用相应的GPU电源配置,可能的值有
        • "default":默认,自动选择
        • "high-performance":高性能模式
        • "low-power":节能模式
      • premultipliedAlpha:boolean,表明排版引擎将假设绘制缓冲区包含预混合alpha通道
      • preserveDrawingBuffer:boolean,如果为true,缓冲区将不会被清除,会保存袭来,直到被清除或被覆盖
      • stencil:boolean,表明绘制缓冲区包含一个深度至少为8为的模板缓冲区

当要获取一个上下文对象的contextAttributes时,可以使用接口context.getContextAttributes()来获取

返回值

  • CanvasRenderingContext2D:当ContextType"2d"
  • WebGLRenderingContext:当ContextType"webgl""experimental-webgl"
  • WebGL2RenderingContext:当ContextType"webgl2""experimental-webgl2"
  • ImageBitmapRenderingContext:当ContextType"bitmaprenderer"

获取上下文事件

canvas获取上下文会触发以下事件:

  • contextlost (experimental):当获取的CanvasRenderingContext2D上下文丢失时会触发
  • contextrestored (experimental):在用户代理恢复CanvasRenderingContext2D时会触发
  • webglcontextcreatingerror:在用户无法创建WebGLRenderingContext上下文时触发
  • webglcontextlost:在用户代理检测到绘制缓冲关联的WebGLRenderingContext上下文丢失时会触发
    - webglcontextrestored:在用户代理恢复WebGLRenderingContext对象的绘制缓冲时会触发

WebGL获取上下文函数的封装

基于以上接口及属性,我们可以封装一个如下的接口(此接口仿照Threejs的初始化方法):

function defaultValue(value, default) {
return value !== undefined ? value : default;
}
function createCanvasElement() {
const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.display = "block";
return canvas;
}
function onContextLost(event) {
event.preventDefault();
console.log("WebGL context lost.");
// TODO 上下文丢失后的处理
}
function onContextRestore(event) {
console.log("WebGL context restored.");
// 用户代理上下文对象恢复后,触发的事件
// 例如,重新创建创建属性对象、材质、纹理、几何、渲染列表等
}
function getContext(parameters) {
const _canvas = defaultValue(parameters.canvas, createCanvasElement()),
_context = defaultValue(parameters.context, null),
_depth = defaultValue(parameters.depth, true),
_stencil = defaultValue(parameters.stencil, true),
_antialias = defaultValue(parameters.antialias, false),
_premultipliedAlpha = defaultValue(parameters.premultipliedAlpha, true),
_preserveDrawingBuffer = defaultValue(parameters.preserveDrawingBuffer, false),
_failIfMajorPerformanceCaveat = defaultValue(parameters.failIfMajorPerformanceCaveat, false),
_powerPreference = defaultValue(parameters.powerPreference, 'default');
let _alpha;
if (parameters.context) {
_alpha = _context.getContextAttributes().alpha;
} else {
_alpha = parameters.alpha !== undefined ? parameters.alpha : false;
}
let _gl = _context;
// 准备上下文参数
const contextAttributes = {
alpha: _alpha,
depth: _depth,
stencil: _stencil,
antialias: _antialias,
premultipliedAlpha: _premultipliedAlpha,
preserveDrawingBuffer: _preserveDrawingBuffer,
failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat,
powerPreference: _powerPreference
};
// 绑定事件,由于我们手动控制上下文的创建过程,此处不绑定webglcontextcreatingerror事件,而是在出现错误时手动处理
_canvas.addEventListener('webglcontextlost', onContextLost, false);
_canvas.addEventListener('webglcontextrestore', onContextRestore, false);
// _canvas.addEventlistener('webglcontextcreatingerror', null, false);
function getWebGLContext(contextNames, contextAttributes) {
for (let i = 0; i < contextnames.length; ++i) {
const contextName = contextNames[ i ];
const context = _canvas.getContext( contextName, contextAttributes );
if ( context !== null ) return context;
}
return null;
}
// 如果当前没有上下文环境,则从下面的参数中查找
if (_gl === null) {
const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl2', 'experimental-webgl' ];
_gl = getWebGLContext(contextNames, contextAttributes);
// 此处再进行一次判断,如果contextAttributes参数中有参数有问题,会造成上下文创建失败
// 如果不加参数创建上下文依然失败,那说明无法创建上下文
if (_gl === null) {
_gl = getWebGLContext(contextNames);
if (_gl) {
// 不带参数创建上下文成功,说明参数有问题
throw new Error("Error creating WebGL context with your selected attributes.");
} else {
// 不带参数也无法创建上下文,说明无法创建上下文
throw new Error("Error creating WebGL context");
}
}
}
return { canvas: _canvas, context: _gl };
}
posted @   李煎饼_GISer  阅读(430)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示