【WebGL系列-01】获取WebGL上下文
1.【WebGL系列-01】获取WebGL上下文
2.【WebGL系列-02】创建program上下文3.【WebGL系列-03】获取shader变量地址及赋值4.【WebGL系列-04】清除缓冲区并绘制图形获取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
:-
当
contextType
为2d
时: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 }; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构