之前一直在捣鼓Vue和React栈,对组件化架构项目有了些理解和体会。今天尝尝WebGL,当然,并不打算现在深入,只是略作了解,我知道这个坑很深。

js的图形库、3d库也有好几款比较流行的,如游戏开发方面的three.js、数据可视化的图表库echarts.js、GIS方面的百度地图、google地图等,最近打算学习下。

言归正传,以前学canvas的时候,只是简单地学习2d context的一些api写写画画,webGL显然更高级些,在MDN文档的介绍中:

WebGL enables web content to use an API based on OpenGL ES 2.0 to perform 3D rendering in an HTML <canvas> in browsers that support it without the use of plug-ins. WebGL programs consist of control code written in JavaScript and special effects code(shader code) that is executed on a computer's Graphics Processing Unit (GPU). WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.

提到了WebGL可以让网页内容中的canvas元素实现3d渲染,其编程由两部分组成,一部分是由js写的控制代码,一部分是在用户设备gpu上执行的实现特定效果的代码(GLSL,注意,GLSL是一门针对GPU的编程语言)。不过WebGL只兼容IE11+

教程假设我们会一些基本的3d图像的概念。Learn WebGL for 2D and 3D graphics这篇入门教程指出,需要我们会一点html和css知识,以及较深的js功底,能理解闭包、原型链、构造函数等概念。

第一步,检测设备是否支持WebGL:

  function detectWebGLContext () {
// Create canvas element. The canvas is not added to the
// document itself, so it is never displayed in the
// browser window.
var canvas = document.createElement("canvas");
// Get WebGLRenderingContext from canvas element.
var gl = canvas.getContext("webgl")
|| canvas.getContext("experimental-webgl");
// Report the result.
if (gl && gl instanceof WebGLRenderingContext) {
paragraph.innerHTML =
"Congratulations! Your browser supports WebGL.";
} else {
paragraph.innerHTML = "Failed to get WebGL context. "
+ "Your browser or device may not support WebGL.";
}
}

跟一般的功能检测一样,其实就是判断  gl = canvas.getContext("webgl")|| canvas.getContext("experimental-webgl")  是不是 WebGLRenderingContext 的一个实例。一旦我们的canvas元素有这个rendering context,我们就可以使用它的api进行渲染。

第二步,开始简单的example

-----填充WebGLContext

1.获取(set up)rendering context ,就是上一步的gl。

2.然后drawing buffer(现在先理解为画布)填充颜色。这个过程分两步:

  //确定渲染的范围
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
//设定WebGL的内部状态--设定颜色
// Set the clear color to darkish green.
gl.clearColor(0.0, 0.5, 0.0, 1.0);
//输出其状态--填充颜色
// Clear the context with the newly set color. This is
// the function call that actually does the drawing.
gl.clear(gl.COLOR_BUFFER_BIT);

gl.viewport()中前两个参数是相对于左下角的距离。后两个是宽,高。

在定义了drawing buffer的 范围后,我们执行了两个动作,先是设定WebGL的内部状态(颜色为绿色),然后执行语句让drawing buffer 变成WebGL内部状态所设定的样子。所以,WebGL实际上是一个状态机。我们可以回想下,在getContext(“2d”)的时候,要画一个矩形,我们也是遵循同样的操作步骤:

//定义样式(即内部状态)
cxt.fillStyle="#FF0000";
//输出图形(将样式状态输出到画布中)
cxt.fillRect(0,0,150,75);

最后,WebGL中颜色定义都是使用RGBA格式的。

-----开始将WebGL和用户交互结合

Clearing by clicking一例由上面的简单例子延伸而来,对canvas和button绑定了click事件,触发switchColor函数。

该函数先判断是否支持WebGL,再确定画布的范围,之后再执行三行代码:

    //产生随机颜色
// Get a random color value using a helper function.
var color = getRandomColor();
//设置WebGL内部状态的颜色新值
// Set the clear color to the random color.
gl.clearColor(color[0], color[1], color[2], 1.0);
//将新值输出到画布
// Clear the context with the newly set color. This is
// the function call that actually does the drawing.
gl.clear(gl.COLOR_BUFFER_BIT);

----裁剪:

  //开启裁剪功能
// Enable scissoring operation and define the position and
// size of the scissoring area.
gl.enable(gl.SCISSOR_TEST);
//设定可更新的区域
gl.scissor(60, 60, 60, 130); // Clear the drawing buffer solid yellow.
gl.clearColor(1.0, 0.6, 0.0, .1);
gl.clear(gl.COLOR_BUFFER_BIT);

getContext("2d")中也有相似的api。只有在指定的区域中画布才会被更新(显示)。

----不设置高宽会导致不符合预期的渲染结果

我们知道设置css可以改变元素的视觉高宽,canvas也一样。但如果我们只是单纯设置了css样式,不对其dom节点设置高宽,将导致诡异的渲染效果。

其实不止“webgl”的RenderingConext,“2d”的context也会有这种情况。

以前研究过canvas这个问题,因为css只是改变canvas元素呈现在页面上的视觉大小,但是其逻辑像素默认是300*150.

当我们调用api时,往api中传入表示高宽或x、y轴位置的参数时,一旦超出y轴方向的150和x轴方向的300,就会超出画布。

所以必要的时候,我们得获取canvas节点,然后js设定其逻辑高宽。canvas.height=xx;canvas.width=xx;

----封装WebGL 方法

function getRenderingContext() {
var canvas = document.querySelector("canvas");
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
var gl = canvas.getContext("webgl")
|| canvas.getContext("experimental-webgl");
if (!gl) {
var paragraph = document.querySelector("p");
paragraph.innerHTML = "Failed to get WebGL context."
+ "Your browser or device may not support WebGL.";
return null;
}
gl.viewport(0, 0,
gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
return gl;
}

这一节没什么新内容,只是把几个基本的语句进行封装。函数做了两件事情,判断是否支持webgl,然后将画布填充成黑色并返回RenderingContext这个接口。

//日后补充

初涉WebGL的更多相关文章

  1. Webgl的2D开发方案(一)spritebatcher

    使用TypeScript 和 webgl 开发   第一步:实现了SpriteBatcher 例子如下 http://oak2x0a9v.bkt.clouddn.com/test/index.html ...

  2. HTML5 学习总结(四)——canvas绘图、WebGL、SVG

    一.Canvas canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术.<canvas> 标记和 ...

  3. 数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇

    <数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇>一文让读者了解了 HT的 2D 拓扑图组件使用,本文将对 HT 的 3D 功能做个综合性的介绍,以便初学者可快速上手使用 HT ...

  4. 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(二)

    我们上一篇<基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)>主要讲解了如何搭建一个实时数据通讯服务器,客户端与服务端是如何通讯的,相信通过上一篇的讲解,再配 ...

  5. 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)

    今天没有延续上一篇讲的内容,穿插一段小插曲,WebSocket 实时数据通讯同步的问题,今天我们并不是很纯粹地讲 WebSocket 相关知识,我们通过 WebGL 3D 拓扑图来呈现一个有趣的 De ...

  6. 基于HTML5的WebGL应用内存泄露分析

    上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...

  7. 基于WebGL 的3D呈现A* Search Algorithm

    http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...

  8. 20个不可思议的 WebGL 示例和演示

    WebGL 是一项在网页浏览器呈现3D画面的技术,有别于过去需要安装浏览器插件,通过 WebGL 的技术,只需要编写网页代码即可实现3D图像的展示.WebGL 可以为 Canvas 提供硬件3D加速渲 ...

  9. webgl 循环传参画10个点

    function main(){ var canvas = document.getElementById("webgl"); var gl = getWebGLContext(c ...

随机推荐

  1. 《HelloGitHub》第 49 期

    兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...

  2. 如何快速地恢复你的win10

    win10清单 这份List不会介绍如何安装系统,而是当面对一个新系统,如何最快的搭建,或者说恢复到一个生产力环境. 必备习惯 备份软件安装包和常用内容上云是高效恢复的两点关键. 备份软件安装包 我的 ...

  3. Scrapy爬虫框架(2)--内置py文件

    Scrapy概念图 这里有很多py文件,分别与Scrapy的各个模块对应 superspider是一个爬虫项目 spider1.py则是一个创建好的爬虫文件,爬取资源返回url和数据 items.py ...

  4. [Batch脚本] if else 的格式

    必须写成一行 ) else (,否则报错. if %abc%=="yes" ( ... ) else ( ... )

  5. 如何优雅的维护 K8S Worker 节点

    前言 正常维护工作节点的流程 当我们要进行 K8S 节点维护时往往需要执行 kubectl drain, 等待节点上的 Pod 被驱逐后再进行维护动作. 命令行如下: kubectl drain NO ...

  6. 抖音人脸识别Autojs脚本

    title: 抖音人脸识别Autojs脚本 用Autojs写的抖音人脸颜值检测脚本 ​ 疫情期间宅家久了,昨天闲着没事(好吧,有事情,但是我不想做) ,消费之火熊熊燃烧.一咬牙把Autojs入正了.我 ...

  7. Codeforces Round #590

    题目链接:Round #590 题目答案:官方Editorial.My Solution A. Equalize Prices Again 签到题还WA了一发,向上取整有点问题: //my wrong ...

  8. CF1328E Tree Queries

    CF1328E Tree Queries 应该还是比较妙的 题意 给你一个树,然后多次询问 每次询问给出一堆节点,问你是否能找到一个从根出发的链,是的对于给出的每个节点,都能找出链上的点,是的他们的距 ...

  9. 学习笔记之MySQL的使用

    什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. 每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据. 我们也可以将数据存储在文 ...

  10. Azure AD(一)入门认识

    一,引言(吹水) 距离上一次介绍Azure Functions的相关博文以及过期快一个月了,本来早早都想好已经规划好的Azure的相关的学习的路线,无奈还是由于自己文笔不好以及自身太懒,导致博文没有更 ...