当前位置: 首页 > 编程日记 > 正文

WebGL初探

目前,我们有很多方案可以快速的接触到 WebGL 并绘制复杂的图形,但最后发现我们忽视了很多细节性的东西。当然,这对初学 WebGL 是有必要的,它能迅速提起我们对 WebGL 的学习兴趣。当学习到更加深入的阶段时,我们更想了解 WebGL 的工作机制,这也将对我们编程有极大的帮助。以上也是我想写这样一个系列的原因。

简介

用更专业的描述讲,WebGL (Web Graphics Library) 是一个用以渲染交互式 3D 和 2D 图形的无需插件且兼容下一代浏览器的 JavaScript API,通过 HTML5 中 <canvas> 元素实现功能。WebGL 是由 Khronos Group 集团制定,而非 W3C 组织。目前,我们可以使用的是 WebGL 第一个版本,它继承自 OpenGL ES 2.0 。而 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA 和游戏主机等嵌入式设备而设计。以下是各版本之间的关系图:

Hello World

首先,我们将通过实现一个简单的 WebGL 程序(清空绘图区)叩开 WebGL 的大门。下面将实现一个最简单的 WebGL 功能:

创建 canvas 元素

WebGL 采用 HTML5 中的 <canvas> 元素。为了使用 WebGL 进行 3D 渲染,你首先需要一个 canvas 元素。这里创建了一个 canvas 元素,并使用 onload 事件创建来初始化 WebGL 上下文。

  1. <body οnlοad="start()">
  2. <canvas id="glcanvas" width="640" height="480">
  3. Your browser doesn't appear to support the HTML5 <code>&lt;canvas&gt;</code> element.
  4. </canvas>
  5. </body>

获取 WebGL 上下文

目前,各浏览器基本都实现了对 WebGL 的支持,但 IE11 及 Edge 浏览器稍微有些不同。以下是对初始化 WebGL 的基本封装:

  1. function initWebGL(canvas) {
  2. // 创建全局变量
  3. window.gl = null;
  4. try {
  5. // 尝试获取标准上下文,如果失败,回退到试验性上下文
  6. gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
  7. }
  8. catch(e) {
  9. throw '创建失败。';
  10. }
  11. // 如果没有GL上下文,马上放弃
  12. if (!gl) {
  13. alert("WebGL初始化失败,可能是因为您的浏览器不支持。");
  14. gl = null;
  15. }
  16. return gl;
  17. }

这里通过采用 canvas 的 getContext(contextType, contextAttributes) 方法判断浏览器是否支持 WebGL,并创建其上下文。当返回值是 canvas 的上下文时,浏览器可支持 WebGL,为 null 时,则创建失败。注意,在 IE11 及 Edge 浏览器下,需要使用 "experimental-webgl" 创建 WebGL,此处做了兼容处理。

清空绘图区

下面将背景颜色设置为黑色,并清空缓存区。

  1. var gl; // WebGL的全局变量
  2. function start() {
  3. var canvas = document.getElementById("glcanvas");
  4. // 初始化 WebGL 上下文
  5. gl = initWebGL(canvas);
  6. // 只有在 WebGL 可用的时候才继续
  7. if (gl) {
  8. // 设置清除颜色为黑色,不透明
  9. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  10. // 清除颜色和深度缓存
  11. gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
  12. }
  13. }

这样,我们可以在浏览器中看到一块黑色区域。你可能已经注意到,WebGL 遵循的是传统 OpenGL 颜色分量的取值范围,从 0.0 到 1.0。RGB 的值越高,颜色越亮。注意,clear() 方法在这里清除颜色和深度缓存,而不是绘制区域的 <canvas>,该方法继承自 OpenGL(基于多缓存模型)。实际还有模版缓存,但实际很少会被用到。

更进一步

上面我们完成了第一个 WebGL 程序,但是我们还未接触到 WebGL 的核心:可编程着色器。接下来,我们将使用可编程着色器在屏幕上绘制点。可编程着色器是一个较为复杂的概念,也有自己的编程语言 GLSL,后面将会又专门的文章具体讲解可编程着色器。这里我们只需要简单了解绘制的流程:

编写着色器程序

  1. // 顶点着色器程序
  2. var VSHADER_SOURCE =
  3. 'void main() {\n' +
  4. '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // 设置顶点位置
  5. '  gl_PointSize = 10.0;\n' +                    // 设置点的大小
  6. '}\n';
  7. // 片元着色器程序
  8. var FSHADER_SOURCE =
  9. 'void main() {\n' +
  10. '  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n' + // 设置点的颜色,此处为白色
  11. '}\n';

上面程序是不是有中似曾相识的感觉?没错,GLSL 语言和 C 语言很类似。着色器程序中包含一个主函数,且返回值为空。其中vec4() 构造函数用于生成一个四维向量(x,y,z,w)。

编译着色器

首先,需要用 createShader( type ) 方法生成相应类型的 WebGLShader。接着,使用 shaderSource( shader, sourceCode ) 作为 GLSL 源码的钩子函数。最后使用 compileShader( shader ) 完成对着色器的编译。程序中我们做了编译后的校验,当着色器编译失败时,会报出失败并删除着色器。

  1. function createShader (gl, type, sourceCode) {
  2. // 编译着色器类型:顶点着色器及片元着色器。
  3. var shader = gl.createShader( type );
  4. gl.shaderSource( shader, sourceCode );
  5. gl.compileShader( shader );
  6. if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
  7. var info = gl.getShaderInfoLog( shader );
  8. console.log( "无法编译 WebGL 程序。 \n\n" + info);
  9. gl.deleteShader(shader);
  10. return null;
  11. }
  12. return shader;
  13. }

连接到可用程序

此时,着色器仍是不可用的,需要将其赋值到 WebGLProgram 上。这里主要进行了三步操作,首先,需要使用 createProgram() 方法创建和初始化一个 WebGLProgram 对象。接着,使用 gl.attachShader(program, shader) 将该对象结合两个已经编译的着色器。最后,使用 linkProgram(program) 将 WebGLProgram 和着色器连接。

  1. function createProgram(gl, vshader, fshader) {
  2. // 创建着色器对象
  3. var vertexShader = createShader(gl, gl.VERTEX_SHADER, vshader);
  4. var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fshader);
  5. if (!vertexShader || !fragmentShader) {
  6. return null;
  7. }
  8. // 创建编程对象
  9. var program = gl.createProgram();
  10. if (!program) {
  11. return null;
  12. }
  13. // 赋值已创建的着色器对象
  14. gl.attachShader(program, vertexShader);
  15. gl.attachShader(program, fragmentShader);
  16. // 连接编程对象
  17. gl.linkProgram(program);
  18. // 检查链接结果
  19. var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
  20. if (!linked) {
  21. var error = gl.getProgramInfoLog(program);
  22. console.log('链接程序失败:' + error);
  23. gl.deleteProgram(program);
  24. gl.deleteShader(fragmentShader);
  25. gl.deleteShader(vertexShader);
  26. return null;
  27. }
  28. return program;
  29. }

使用可用着色器程序

这一步主要使用 useProgram(program) 方法告诉 GPU 使用程序。

  1. function initShaders(gl, vshader, fshader) {
  2. var program = createProgram(gl, vshader, fshader);
  3. if (!program) {
  4. console.log('创建程序失败。');
  5. return false;
  6. }
  7. gl.useProgram(program);
  8. gl.program = program;
  9. return true;
  10. }

绘制一个点

最后,使用 drawArrays(mode, first, count) 绘制一个点,该函数是一个非常强大的渲染函数,后续文章会有详细介绍。此处只需要知道传入 "POINTS" 绘制了一个点。

  1. // 绘制一个点
  2. gl.drawArrays(gl.POINTS, 0, 1);

至此,我们已经完成了绘制一个点的全部程序。当运行以上程序时,我们会在浏览器中看到一个白色的点。

结束语

到现在,我们虽然还没有使用 WebGL 绘制三维图形,但我们已经进入了 WebGL 世界。我们已经使用 WebGL 绘制了简单的图形。但是这只是 WebGL 的绘制的冰山一角,我们使用 WebGL 当然不是为了绘制这样一个简单的图形。为了绘制更复杂的图形,我们还有很多的细节需要去了解。但是无论如何,我们都已经开启了 WebGL 的第一步,其实问题也并没有我们想象的那么难。


作者:sundway

来源:51CTO

相关文章:

Linux下用C语言最基本的程序开发与调试

1.建一个目录2.写代码&#xff0c;建一个hello.c文件代码&#xff1a;view plaincopy to clipboardprint?#include "stdio.h" main() { printf("Hello Linux.\n") } #include "stdio.h" main() { printf("Hello Linux.\n")…

全面升级!星环科技基础软件再升级,赋能数字中国建设

3月24日&#xff0c;星环科技举行2021线上发布会&#xff0c;支持10种主流数据模型的多模数据平台和数据云产品、实现AI建模的全生命周期管理人工智能等产品新版本齐齐亮相。 星环科技坚持核心技术自主原创&#xff0c;专注于大数据基础平台、分布式关系型数据库、数据开发与智…

脚本中echo显示内容带颜色显示

脚本中echo显示内容带颜色显示,echo显示带颜色&#xff0c;需要使用参数-e格式如下&#xff1a;echo -e "\033[字背景颜色&#xff1b;文字颜色m字符串\033[0m"例如&#xff1a;echo -e "\033[41;36m something here \033[0m"其中41的位置代表底色&#xf…

Java 8默认方法会破坏你的(用户的)代码

Java 8的默认方法试图尝试更进一步简化Java API。不幸的是&#xff0c;这一最近的语言扩展带来了一系列复杂的规则&#xff0c;但只有少部分Java开发者意识到这一点。这篇文章告诉你为什么引入默认方法会破坏你的&#xff08;用户的&#xff09;代码。 起初看来&#xff0c;默认…

JPA多对多关联

关于JPA多对多关系&#xff0c;这是使用学生与教师来表示。一个Student由多个Teacher教&#xff0c;同样一个Teacher也可以教多个学生。Student类如下&#xff1a; 1 package com.yichun.bean;2 3 import java.util.HashSet;4 import java.util.Set;5 6 import javax.persisten…

上市之后,青云存储平台 QingStor 也要“进军”云原生

作者 | 夕颜头图 | 下载于东方IC出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;3 月 16 日&#xff0c;北京青云科技股份有限公司&#xff08;以下简称“青云科技”&#xff09;登录科创板&#xff0c;昔日里频频出现在公众视野的云计算企业&#xff0c;终…

SQL Server 存储过程的分页方案比拼

建立表&#xff1a; CREATE TABLE [TestTable] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL , [LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL , [Country] [nvarchar] (50) COLLATE Chinese_PRC_CI…

未来黑客入侵的不仅有电脑,还有人脑?

提到黑客入侵&#xff0c;我们能够知道的领域有很多&#xff0c;比如企业数据库、金融系统、个人信息、个人账户等。随着时代的变迁&#xff0c;人工智能、云计算、物联网等相继崛起&#xff0c;可能给黑客攻击的领域变得越发宽广。可是如果说黑客能攻击控制的不仅仅是电脑&…

不需xp_cmdshell支持在有注入漏洞的SQL服务器上运行CMD命令

我的BLOG里有一篇文章介绍了关于SQL注入的基本原理和一些方法。最让人感兴趣的也许就是前面介绍的利用扩展存储过程xp_cmdshell来运行操作系统的控制台命令。这种方法也非常的简单&#xff0c;只需使用下面的SQL语句&#xff1a;EXEC master.dbo.xp_cmdshell dir c:/但是越来越…

谷歌低调了 5 年的 Fuchsia OS,终于有望面世了!

种种迹象表明&#xff0c;低调了多年的 Fuchsia OS 可能就要出首个开发者版本了&#xff01;整理 | 郑丽媛出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;千呼万唤始出来&#xff0c;等待了五年&#xff0c;谷歌 Fuchsia OS 的首个开发者版本终于有望面世了&#…

chrom扩展开发-入门

2019独角兽企业重金招聘Python工程师标准>>> 先了解一下chrome的两种功能延伸方式&#xff1a; * 扩展&#xff08;Extension&#xff09; 1.指的是通过调用 Chrome 提供的 Chrome API 来扩展浏览器功能的一种组件&#xff0c;工作在浏览器层面&#xff0c;使用 HT…

你的机器学习模型为什么会出错?奉上四大原因解析及五条改进措施

对开发者来说&#xff0c;目前有一系列的机器学习模型可供选择。雷锋网(公众号&#xff1a;雷锋网)了解&#xff0c;可以用线性回归模型预测具体的数值&#xff0c;用逻辑回归模型对不同的运算结果进行归类&#xff0c;以及用神经网络模型处理非线性的问题等等。 不论哪一种&am…

释放CPU,算力经济下DPU芯片的发展机遇

当前承载算力的基础设施是各种规模的的数据中心&#xff0c;从几十个服务器节点的小规模企业级计算中心到数万个节点的巨型数据中心&#xff0c;通过云计算的模式对应用层客户提供存储、软件、计算平台等服务。这个生态直接承载了全球数十万亿美元规模的数字经济&#xff0c;而…

SQLserver安全设置攻略

日前SQL INJECTION的攻击测试愈演愈烈&#xff0c;很多大型的网站和论坛都相继被注入。这些网站一般使用的多为SQLSERVER数据库&#xff0c;正因为如此&#xff0c;很多人开始怀疑SQL SERVER的安全性。其实SQL SERVER2000已经通过了美国政府的C2级安全认证-这是该行业所能拥有的…

undefined symbol: ap_log_rerror;apache2.4与weblogic点so文件

没法子啊&#xff1b;只能用 httpd-2.2.26 https://www.google.com.hk/#newwindow1&qundefinedsymbol:ap_log_rerror&safestrictundefined symbol: ap_log_rerror[rootlocalhost local]# vi apache2/conf/httpd.conf[rootlocalhost local]# ./apache2/bin/apachectl s…

10个Java 8 Lambda表达式经典示例

Java 8 刚于几周前发布&#xff0c;日期是2014年3月18日&#xff0c;这次开创性的发布在Java社区引发了不少讨论&#xff0c;并让大家感到激动。特性之一便是随同发布的lambda表 达式&#xff0c;它将允许我们将行为传到函数里。在Java 8之前&#xff0c;如果想将行为传入函数&…

Sql server 2005带来的分页便利

select threadid from (select threadid, ROW_NUMBER() OVER (order by stickydate) as Pos from cs_threads) as T where T.Pos > 100000 and T.Pos < 100030 如果里面的这个表cs_threads数据量超大&#xff0c;比如&#xff0c;几亿条记录&#xff0c;那这个方法应该是…

想学Python?快看看这个教程!收藏!

Python入门从哪开始&#xff0c;90%以上的书上都是这样讲的&#xff1a;先介绍 Python 的基本语法规则、list、dict、tuple 等数据结构&#xff0c;然后再介绍字符串处理和正则表达式&#xff0c;介绍文件等IO操作.... 就这样一点一点往下说。然而这种按部就班的学习方法&#…

Struts1.x系列教程(4):标签库概述与安装

Struts的整个视图层&#xff08;就是MVC模式中的View层&#xff09;是由Struts的定制标签&#xff08;或者称为定制动作&#xff09;和客户端代码(Javascript、HTML等)实现的。这些Struts标签被写在JSP页面中&#xff0c;用于生成客户端代码、进行逻辑判断等工作&#xff0c;使…

绿盟科技与CCF成立“鲲鹏”科研基金 计划发力5大领域资助16个项目

【51CTO.com原创稿件】2017年5月10日&#xff0c;由中国计算机学会(CCF)和北京神州绿盟信息安全科技股份有限公司(以下简称&#xff1a;绿盟科技)主办的2017 CCF-绿盟科技“鲲鹏”科研基金新闻发布会于北京隆重举行。双方共同宣布“鲲鹏”科研基金正式成立&#xff0c;该基金将…

修改SQL SERVER内置存储过程

SQLSERVER估计是为了安装或者其它方面&#xff0c;它内置了一批危险的存储过程。能读到注册表信息&#xff0c;能写入注册表信息&#xff0c;能读磁盘共享信息等等……各位看到这儿&#xff0c;心里可能会在想&#xff0c;我的网站中有其它的代码&#xff0c;又不像查询分析器那…

〖Linux〗使用Qt5.2.0开发Android的NDK应用程序

2013年12月11日&#xff0c;Qt发布了其新的Qt版本&#xff1a;Qt5.2.0&#xff1b; 利用这个新的版本&#xff0c;我们可以很轻松地制作出Android手机的NDK应用程序。 开发环境&#xff1a;Ubuntu13.10 x86_64 下载链接&#xff1a;http://download.qt-project.org/official_re…

基于 OpenCV 的面部关键点检测实战

【 编者按】这篇文章概述了用于构建面部关键点检测模型的技术&#xff0c;这些技术是Udacity的AI Nanodegree程序的一部分。作者 | 小白责编 | 欧阳姝黎概述在Udacity的AIND的最终项目中&#xff0c;目标是创建一个面部关键点检测模型。然后将此模型集成到完整的流水线中&#…

气温上升影响数据中心节能

也许一些公司都是你熟悉的名字。但你可能不知道的是&#xff0c;这样的公司拥有遍布美国的大型数据中心&#xff0c;包括北弗吉尼亚州。数据中心用于存储、备份和通信业务&#xff0c;使用了大量的电力&#xff0c;为IT设备供电&#xff0c;并保持其冷却其数据中心基础设施。 也…

如何将SQL Server表驻留内存和检测

将SQL Server数据表驻留内存是SQL Server提供的一项功能&#xff0c;在一般小型系统的开发过程中估计很少会涉及到。这里整理了相关文档资料&#xff0c;演示如何把SQL Server中一个表的所有数据都放入内存中&#xff0c;实现内存数据库&#xff0c;提高实时性。 1, DBCC PINTA…

C 一样快,Ruby 般丝滑的 Crystal 发布 1.0 版本,你看好吗?

整理 | 寇雪芹 头图 | 下载于视觉中国 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 近日&#xff0c;编程语言 Crystal 发布了 1.0 版本。 Crystal 是一种通用的、面向对象的编程语言&#xff0c;其语法受到 Ruby 语言的启发&#xff0c;具有静态类型检查功能&am…

php in yii framework

为什么80%的码农都做不了架构师&#xff1f;>>> command line php yiic defined(STDIN) or define(STDIN, fopen(php://stdin, r));$_SERVER[argv](2013-12-30 22:44:10) 最近读这本书, 讲使用方法, 每章节各自独立, 配合些源码看(但不要细看, 会干扰进度, 浪费时…

selenium grid2 使用远程机器的浏览器

下载 selenium-server-standalone-3.4.0.jar包在selenium-server-standalone-3.4.0.jar包目录下面执行cmd 命令 java -jar selenium-server-standalone-3.4.0.jar -role hub 启用selenium grid hub&#xff0c; 默认端口 4444注册浏览器客户端&#xff0c;命令行执行&#xff…

Create a restful app with AngularJS/Grails(4)

为什么80%的码农都做不了架构师&#xff1f;>>> #Standalone AngularJS application In the real world applications, it is usually required to integrate the third party APIs into the project. Most of case, the third party service is provided as flexi…

无代码的时代真的来了吗?

所谓“无代码”&#xff0c;并不是不存在代码&#xff0c;无代码平台的开发&#xff0c;给开发者更大的挑战、更多 机会。所以&#xff0c;“无代码”不是解放程序员&#xff0c;而是给程序员提出了更高的要求、带来更大的挑战。作者 | 函子科技陆继恒&#xff0c;Jessica Tang…