WebGL 响应上下文丢失解决方案

目录

响应上下文丢失

如何响应上下文丢失

上下文事件

示例程序(RotatingTriangle_contextLost.js)


响应上下文丢失

WebGL使用了计算机的图形硬件,而这部分资源是被操作系统管理,由包括浏览器在内的多个应用程序共享。在某些特殊情况下,如另一个程序接管了图形硬件,或者操作系统进入休眠,浏览器就会失去使用这些资源的权利,并导致存储在硬件中的数据丢失。在这种情况下,WebGL绘图上下文就会丢失。比如,如果你正在一台笔记本电脑或智能手机上运行WebGL程序,如下图(左)所示,然后使其进入休眠状态,通常此时浏览器的控制台会显示一条错误新消息。当你将电脑或手机重新唤醒后,操作系统确实回到了休眠前的状态,但是浏览器中运行的WebGL程序却不见了,如下图(右)所示。网页的背景色是白色,所以浏览器上一片空白。

比如,当你运行RotatingTriangle程序并使计算机进入休眠,控制台上可能会显示: 

WebGL error CONTEXT_LOST_WEBGL in uniformMatrix4fv([object WebGLUniformLocation,false,[object Float32Array]] 

这条信息表示,系统进入休眠状态前或被唤醒后,浏览器正在调用gl.uniform-Matrix4fv()函数并出错了。这条消息的具体内容依赖于进入上下文丢失时程序正在做什么。这一节就来解释如何处理上下文丢失的问题。 

如何响应上下文丢失

如前所述,在某些情况下,上下文可能会丢失。实际上,WebGL提供了两个事件来表示这种情况,上下文丢失事件(webglcontextlost)和上下文恢复事件(webglcontextrestored)。如表10.4所示。

上下文事件

当上下文事件丢失的时候,由getWebGLContext()函数获得的渲染上下文对象gl就失效了,而之前在gl上的所有操作,如创建缓冲区对象和纹理对象、初始化着色器、设置背景色等等,也都失效了。浏览器重置WebGL系统后,就触发了上下文恢复事件,这时我们需要重新完成上述步骤。在JavaScript中保存的变量不会受到影响,可以照常使用。

研究示例代码前,我们需要使用<canvas>的addEventListener()函数注册上下文丢失事件和上下文恢复事件的响应函数。你应该还记得,之前我们直接通过<canvas>元素的onmousedown属性来注册鼠标事件响应函数,但是<canvas>并不支持某个特殊的属性来注册关于上下文事件的响应函数,所以必须使用addEventListener()函数。

 示例程序(RotatingTriangle_contextLost.js)

我们建立了示例程序RotatingTriangle_contextLost,该示例程序修改了RotatingTriangle,使其能够处理上下文丢失事件,如上所示。如下显示了程序的代码。 

var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'uniform mat4 u_ModelMatrix;\n' +'void main() {\n' +'  gl_Position = u_ModelMatrix * a_Position;\n' +'}\n';
var FSHADER_SOURCE ='void main() {\n' +'  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +'}\n';function main() {var canvas = document.getElementById('webgl'); // 获取canvas元素// 注册事件响应函数以处理上下文丢失和恢复事件canvas.addEventListener('webglcontextlost', contextLost, false); canvas.addEventListener('webglcontextrestored', function(ev) { start(canvas); }, false);start(canvas);   // 开始与WebGL相关的过程
}var ANGLE_STEP = 45.0;
var g_currentAngle = 0.0; // 从局部变量改为全局变量
var g_requestID; // requestAnimationFrame() 函数的返回值
function start(canvas) {// 获取WebGL渲染上下文var gl = getWebGLContext(canvas);if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) returnvar n = initVertexBuffers(gl);   // Write the positions of vertices to a vertex shadergl.clearColor(0.0, 0.0, 0.0, 1.0);   // Specify the color for clearing <canvas>var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');var modelMatrix = new Matrix4();   // Create a model matrixvar tick = function() {    // Start drawingg_currentAngle = animate(g_currentAngle);                // Update current rotation angledraw(gl, n, g_currentAngle, modelMatrix, u_ModelMatrix); // Draw the triangleg_requestID = requestAnimationFrame(tick, canvas);       // Reregister this Function again};tick();
}function contextLost(ev) { // 上下文丢失事件响应函数cancelAnimationFrame(g_requestID); //  停止动画ev.preventDefault();  // 阻止默认行为
}function initVertexBuffers(gl) {var vertices = new Float32Array ([0.0, 0.5,   -0.5, -0.5,   0.5, -0.5]);var n = 3;   // The number of verticesvar vertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);var a_Position = gl.getAttribLocation(gl.program, 'a_Position');gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(a_Position);gl.bindBuffer(gl.ARRAY_BUFFER, null);return n;
}function draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {modelMatrix.setRotate(currentAngle, 0, 0, 1);gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, n);
}var g_last = Date.now();
function animate(angle) {var now = Date.now();var elapsed = now - g_last;g_last = now;var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;return newAngle %= 360;
}

处理上下文丢失的过程与着色器没有关系,而发生在main()函数中。本例的main()函数非常简单:首先分别注册上下文丢失和上下文恢复事件响应函数(第15、16行),然后调用start()方法(第17行),就结束了。

start()函数执行了RotatingTriangle.js中main()函数的大部分逻辑(第23行),当上下文丢失又恢复后,应当再次调用该函数。为了处理上下文恢复时重新初始化WebGL程序,start()函数有两处重要的改变。

首先,程序将三角形的当前角度存储在全局变量g_currentAngle而不是局部变量中(第21行),这样当上下文恢复之后,就能从中获取角度以绘制三角形。其次,为了在上下文丢失后停止动画(即停止反复调用tick()函数),程序还将requestAnimationFrame()函数的返回值保存在全局变量g_requestID中(第22行)。

下面来看上下文事件响应函数。上下文丢失事件响应函数contextLost()只有两行,停止调用产生动画的函数以保证在上下文恢复之前不再尝试重绘(第40行),以及阻止浏览器对该事件的默认处理行为(第41行)。浏览器对上下文丢失事件的默认处理行为是,不再触发上下文恢复事件,而本例需要触发该事件,所以我们要阻止浏览器的默认行为。

上下文恢复事件响应函数很简单,直接调用start()函数以重置WebGL系统,所以我们将其定义为匿名函数(第16行)。

注意,当触发上下文丢失事件时,浏览器总会在控制台显示下面这样一行警告:

WARNING: WebGL content on the page might have caused the graphics card to reset

通过响应上下文丢失事件,WebGL程序就能够在上下文丢失的情况下也能正常运行。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/94993.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java-LangChain:使用 ChatGPT API 搭建系统-5】处理输入-思维链推理

第五章&#xff0c;处理输入-思维链推理 在本章中&#xff0c;我们将专注于处理输入&#xff0c;即通过一系列步骤生成有用地输出。 有时&#xff0c;模型在回答特定问题之前需要进行详细地推理。如果您参加过我们之前的课程&#xff0c;您将看到许多这样的例子。有时&#xf…

逐步解决Could not find artifact com:ojdbc8:jar:12

Could not find artifact com:ojdbc8:jar:12 in central (https://repo.maven.apache.org/maven2) 原因&#xff1a; ojdbc8:jar:12 属于Oracle 数据库链接的一个程序集&#xff0c;缺失的话很有可能会影响数据库链接&#xff0c;蝴蝶效应产生不可预测的BUG&#xff01;但是版…

OpenGLES:绘制一个混色旋转的3D立方体

效果展示 混色旋转的3D立方体 一.概述 之前关于OpenGLES实战开发的博文&#xff0c;不论是实现相机滤镜还是绘制图形&#xff0c;都是在2D纬度 这篇博文开始&#xff0c;将会使用OpenGLES进入3D世界 本篇博文会实现一个颜色渐变、旋转的3D立方体 动态3D图形的绘制&#xf…

mybatise-plus的id过长问题

一、问题情景 笔者在做mp插入数据库(id已设置为自增)操作时&#xff0c;发现新增数据的id过长&#xff0c;结果导致前端JS拿到的数据出现了精度丢失问题&#xff0c;原因是后端id的类型是Long。在网上查了一下&#xff0c;只要在该属性上加上如下注解就可以 TableId(value &q…

进程调度的时机,切换与过程以及方式

1.进程调度的时机 进程调度&#xff08;低级调度〉&#xff0c;就是按照某种算法从就绪队列中选择一个进程为其分配处理机。 1.需要进行进程调度与切换的情况 1.当前运行的进程主动放弃处理机 进程正常终止运行过程中发生异常而终止进程主动请求阻塞&#xff08;如等待l/O)…

大模型部署手记(1)ChatGLM2+Windows GPU

1.简介&#xff1a; 组织机构&#xff1a;智谱/清华 代码仓&#xff1a;https://github.com/THUDM/ChatGLM2-6B 模型&#xff1a;THUDM/chatglm2-6b 下载&#xff1a;https://huggingface.co/THUDM/chatglm2-6b 镜像下载&#xff1a;https://aliendao.cn/models/THUDM/chat…

很普通的四非生,保研破局经验贴

推免之路 个人情况简介夏令营深圳大学情况机试面试结果 预推免湖南师范大学面试结果 安徽大学面试结果 北京科技大学笔试面试结果 合肥工业大学南京航空航天大学面试结果 暨南大学东北大学 最终结果一些建议写在后面 个人情况简介 教育水平&#xff1a;某中医药院校的医学信息…

.netCore .net5,6,7 存日志文件

如果你使用 .netCore及以上版本(.net5,.net6,.net7)... 系统默认自带日志中间件(log4net) 对,就是上次java 日志大漏洞的兄弟....... 控制台自动打印日志就是它的功劳 现在我们想存日志文件,怎么办 很简单. 1.在项目中添加日志配置文件 文件名 : log4net.config 不能…

uniapp echarts 适配H5与微信小程序

文章目录 前言一、修改 ec-canvas组件1.1 在ec-canvas组件methods中定义一个initChart方法1.2 用initChart全局替换this.ec.onInit1.3 监听数据变化1.4 ec-canvas完整代码参考 二、H5 echarts组件三、供外部调用的组件外部调用组件 uni-chart代码使用uni-chart 前言 接上文&…

Discuz!X 3.4任意文件删除漏洞

复现过程&#xff1a; 1.访问http://x.x.x/robots.txt&#xff08;文件存在&#xff09; 2.登录弱口令 账号&#xff1a;admin密码&#xff1a;admin 3.来到个人设置页面找到自己的formhash&#xff1a; 4.点击保存&#xff0c;抓包 来到这个参数&#xff1a;birthprovin…

力扣 -- 879. 盈利计划(二维费用的背包问题)

解题步骤&#xff1a; 参考代码&#xff1a; 未优化的代码&#xff1a; class Solution { public:int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {//计划数int lengroup.size();//每一维都多开一行空间vector&…

websocket逆向【python实现websocket拦截】

python实现websocket拦截 前言一、拦截的优缺点优点:缺点:二、实现方法1.环境配置2.代码三、总结前言 开发者工具F12,筛选ws后,websocket的消息是这样显示的,如何获取这里面的消息呢? 以下是本篇文章正文内容 一、拦截的优缺点 主要讲解一下websocket拦截的实现,现在…

使用Pytorch从零实现Vision Transformer

在这篇文章中,我们将基于Pytorch框架从头实现Vision Transformer模型,并附录完整代码。 Vision Transformer(ViT)是一种基于Transformer架构的深度学习模型,用于处理计算机视觉任务。它将图像分割成小的图像块(patches),然后使用Transformer编码器来处理这些图像块。V…

网络代理的多面应用:保障隐私、增强安全和数据获取

随着互联网的发展&#xff0c;网络代理在网络安全、隐私保护和数据获取方面变得日益重要。本文将深入探讨网络代理的多面应用&#xff0c;特别关注代理如何保障隐私、增强安全性以及为数据获取提供支持。 1. 代理服务器的基本原理 代理服务器是一种位于客户端和目标服务器之间…

VC++创建windows服务程序

目录 1.关于windows标准可执行程序和服务程序 2.服务相关整理 2.1 VC编写服务 2.2 服务注册 2.3 服务卸载 2.4 启动服务 2.5 关闭服务 2.6 sc命令 2.7 查看服务 3.标准程序 3.1 后台方式运行标准程序 3.2 查找进程 3.3 终止进程 以前经常在Linux下编写服务器程序…

【LeetCode热题100】--20.有效的括号

20.有效的括号 使用栈&#xff1a; class Solution {public boolean isValid(String s) {Stack<Character> stack new Stack<>();int num s.length();for(int i 0;i<num;i){char c s.charAt(i);if(c(||c[||c{){stack.push(c);}else if(stack.isEmpty() ||c…

ubuntu终端 中文显示 改为 英文显示

临时有效 如果希望终端显示英文&#xff0c;可以在终端设置环境变量 export LC_ALLC 若希望取消环境变量 unset LC_ALL 实际是改变系统两个环境变量 $LANGUAGE 和 $LANG的值&#xff08;可以用echo $LANG 来查看值&#xff09; 永久有效&#xff1b; 1.打开终端&#xf…

Lagrange插值法实验:求拉格朗日插值多项式和对应x的近似值matlab实现(内附代码)

一、实验要求 已知函数表&#xff1a; 求出Lagrange 插值多项式&#xff0c;并计算x1.2处的y的近似值。 二、MATLAB代码 求解多项式&#xff1a; X input(请输入横坐标向量X:\nX); % 获取用户输入的横坐标向量 Y input(请输入纵坐标向量Y:\nY); % 获取用户输入的纵坐标…

Java 基于 SpringBoot+Vue 的留守儿童关爱网站

文章目录 1.研究背景2. 技术栈3.系统分析4系统设计5系统的详细设计与实现5.1系统功能模块5.2管理员功能模块 源码下载地址 1.研究背景 以往的留守儿童爱心的管理&#xff0c;一般都是纸质文件来管理留守儿童爱心信息&#xff0c;传统的管理方式已经无法满足现代人们的需求&…

[AOSP] [JNI] [Android] AOSP中使用JNI

一. 简要 &#x1f34e; JNI是Java Native Interface的缩写&#xff0c;它提供了若干的API实现了Java和其他语言的通信&#xff08;主要是C&C&#xff09;。从Java1.1开始&#xff0c;JNI标准成为java平台的一部分&#xff0c;它允许Java代码和其他语言写的代码进行交互。J…