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

news2024/9/8 23:52:42

目录

响应上下文丢失

如何响应上下文丢失

上下文事件

示例程序(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)) return
  var n = initVertexBuffers(gl);   // Write the positions of vertices to a vertex shader
  gl.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 matrix
  var tick = function() {    // Start drawing
    g_currentAngle = animate(g_currentAngle);                // Update current rotation angle
    draw(gl, n, g_currentAngle, modelMatrix, u_ModelMatrix); // Draw the triangle
    g_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 vertices
  var 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.coloradmin.cn/o/1061788.html

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

相关文章

BIT-5-操作符详解(C语言初阶学习)

1. 各种操作符的介绍。 2. 表达式求值 1. 操作符分类&#xff1a; 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 除了 % 操作符…

【实战】流动的箭头 —— 线性流动组件(repeating-linear-gradient,@keyFrames)

文章目录 一、引子二、组件思路三、效果图四、源代码src\components\flow-arrow\index.jssrc\components\flow-arrow\keyFrames.jssrc\components\flow-arrow\constant.js组件调用 五、拓展学习1.repeating-linear-gradient2.animation3.keyFrames 组件源码获取&#xff1a;⭐️…

docker 安装 logstash

文章目录 Logstash基本语法组成什么是Logstash配置文件&#xff1a;拉去镜像启动镜像 Logstash输入插件&#xff08;input&#xff09;1、标准输入(Stdin)2、读取文件(File) Logstash基本语法组成 什么是Logstash logstash是一个数据抽取工具&#xff0c;将数据从一个地方转移…

Dubbo3应用开发—协议(Dubbo协议、REST协议 、gRPC协议、Triple协议)

协议 协议简介 什么是协议 Client(Consumer端)与Server&#xff08;Provider端&#xff09;在传输数据时双方的约定。 Dubbo3中常见的协议 1.dubbo协议[前面文章中使用的都是dubbo协议] 2.rest协议 3.triple协议 4.grpc协议 5.thirft协议 6.webservice协议 7.rocketmq协议 …

回归预测 | MATLAB实现PSO-SVR粒子群优化支持向量机回归多输入单输出预测

回归预测 | MATLAB实现PSO-SVR粒子群优化支持向量机回归多输入单输出预测 目录 回归预测 | MATLAB实现PSO-SVR粒子群优化支持向量机回归多输入单输出预测预测效果基本介绍模型描述程序设计预测效果 <

【Unet系列】

https://tianfeng.space/1947.html 前言概念 图像分割 分割任务就是在原始图像中逐像素的找到你需要的家伙! 语义分割 就是把每个像素都打上标签&#xff08;这个像素点是人&#xff0c;树&#xff0c;背景等&#xff09; &#xff08;语义分割只区分类别&#xff0c;不区…

Android Studio编写xml布局不提示控件的部分属性问题的解决

最近突然发现Android Studio编写xml&#xff0c;发现有一部分控件的属性没有了代码提示&#xff0c;主要体现为id,margin等属性不再有代码提示&#xff0c;如下图。 但是手动输入仍然有效。然后删掉Android Sdk重新回来还是发现有问题&#xff0c;导一个之前的旧项目进来&#…

Mysql技术文档--慢mysql的优化--工作流--按步排查

这里是用来发现慢sql的一个好方法 --by.阿丹 Prometheus-监控Mysql进阶用法(1)&#xff08;安装配置&#xff09;_一单成的博客-CSDN博客 阿丹&#xff1a; 知道了慢sql的语句那么就开始按照优化步骤对sql进行排查和优化。 1、阅读sql逻辑 首先观察sql语句的书写&#xff0…

智慧邮政:浅述视频监控与AI智能分析技术助力邮政物流智能监管

随着电子商务的蓬勃发展&#xff0c;我国的快递业务量也随之增长&#xff0c;邮政快递业的规模也在不断扩大。快递业务的迅猛发展促进了快递网点数量的爆发式增长&#xff0c;同时也带来了成本投入增加、服务质量下降等各种管理问题。快递企业每年因快递损毁、丢件等事件造成的…

棉花叶病害数据集

Bacterial Blight&#xff08;细菌性枯萎病&#xff09;&#xff1a;细菌性枯萎病是由细菌引起的棉花疾病&#xff0c;主要受害部位是棉花的叶子和茎。这种病害可以导致叶片枯萎、变色和腐烂&#xff0c;对棉花产量产生不利影响。 Curl Virus&#xff08;卷叶病毒&#xff09;…

对比表:阿里云轻量应用服务器和服务器性能差异

阿里云服务器ECS和轻量应用服务器有什么区别&#xff1f;轻量和ECS优缺点对比&#xff0c;云服务器ECS是明星级云产品&#xff0c;适合企业专业级的使用场景&#xff0c;轻量应用服务器是在ECS的基础上推出的轻量级云服务器&#xff0c;适合个人开发者单机应用访问量不高的网站…

TF坐标变换

ROS小乌龟跟随 5.1 TF坐标变换 Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 tf模块&#xff1a;在 ROS 中用于实现不同坐标系之间的点或向量的转换。 在ROS中坐标变换最初对应的是tf&#xff0c;不过在 hydro 版本开始, tf 被弃用&#xff0c;迁移到 tf2,后者更…

Flv.js编译使用

Flv.js &#xff08;https://github.com/bilibili/flv.js&#xff09;是 HTML5 Flash 视频&#xff08;FLV&#xff09;播放器&#xff0c;纯原生 JavaScript 开发&#xff0c;没有用到 Flash。由 bilibili 网站开源。本文讲述其编译使用。 Flv.js目前最新版本是v1.6.2。在htt…

《视觉 SLAM 十四讲》V2 第 5 讲 相机与图像

文章目录 相机 内参 && 外参5.1.2 畸变模型单目相机的成像过程5.1.3 双目相机模型5.1.4 RGB-D 相机模型 实践5.3.1 OpenCV 基础操作 【Code】OpenCV版本查看 5.3.2 图像去畸变 【Code】5.4.1 双目视觉 视差图 点云 【Code】5.4.2 RGB-D 点云 拼合成 地图【Code】 习题题…

美妆护肤品商城小程序的作用是什么?

化妆品几乎可以覆盖所有人群&#xff0c;各式各样的品牌及经销商非常多&#xff0c;主要销售模式为门店零售、线上入驻电商平台售卖、批发等&#xff0c;近些年随着电商发展迭代以及消费升级&#xff0c;对品牌或经销商来说&#xff0c;传统经营模式变得低效&#xff0c;每个人…

华为云云耀云服务器L实例评测|Uniapp开发部署茶叶商城小程序、H5

1、华为云云耀云服务器L实例评测&#xff5c;Uniapp开发茶叶商城小程序、H5 华为云耀云服务器L实例是新一代开箱即用、面向中小企业和开发者打造的全新轻量应用云服务器。多种产品规格&#xff0c;满足您对成本、性能及技术创新的诉求。云耀云服务器L实例提供丰富严选的应用镜像…

Spring Security 6.1.x 系列 (1)—— 初识Spring Security

一、 Spring Security 概述 Spring Security是Spring组织提供的一个开源安全框架&#xff0c;基于Spring开发&#xff0c;所以非常适合在Spring Boot中使用。 官方文档地址&#xff1a;https://docs.spring.io/spring-security/reference/index.html GitHub地址&#xff1a;…

抖音小店怎么运营?运营全流程,不懂的快来看!

我是电商珠珠 抖音小店是抖音旗下的电商平台&#xff0c;对于抖音来说流量是充足的&#xff0c;所以很多人想要在抖音小店上下功夫。 但是关于抖音小店的流程很多人还不太熟悉&#xff0c;今天我就来给大家详细的讲一下。 一、入驻准备 在入驻的时候&#xff0c;需要办理一…

lv7 嵌入式开发-网络编程开发 09 UDP通信

目录 1 用到的相关API 1.1 write/read到send/recv 1.2 sendto与recvfrom 2 UDP通信的实现过程 3 服务端代码、客户端、makefile代码实现 1 用到的相关API 1.1 write/read到send/recv send函数原型&#xff1a; ssize_t send(int sockfd, const void *buf, size_t len, …

Ubuntu MySQL

在安装前&#xff0c;首先看你之前是否安装过&#xff0c;如果安装过&#xff0c;但是没成功&#xff0c;就要先卸载。 一、卸载 1.查看安装 dpkg --list | grep mysql 有东西&#xff0c;就说明您之前安装过mysql。 2.卸载 先停掉server sudo systemctl stop mysql.servic…