文章目录

  • 1. 概述
  • 2. 示例:绘制一个点
    • 1) HelloPoint1.html
    • 2) HelloPoint1.js
      • (1) 准备工作
      • (2) 着色器
      • (3) 顶点着色器
      • (4) 片元着色器
      • (5) 清空缓冲区
      • (6) 绘制操作
  • 3. 结果
  • 4. 参考

1. 概述

不得不说现在三维图形渲染技术更新换代实在是太快,OpenGL很多资料还没来得及学习就已经有点落伍了。NeHe的学习教程还有之前用的《OpenGL编程指南》第七版(也就是红宝书)都非常好,可惜它们都是从固定管线开始讲起的;而现在可编程管线的技术已经是非常常见的基础技术了。后来我还看过《OpenGL编程指南》第八版(白皮书),这本教程是从可编程管线(着色器)开始讲起的,看的时候就觉得没有前面的基础打底,显得非常的晦涩,远不如红宝书易懂。羞愧的说,我已经多次入门失败了。

这也正是我写这篇教程的原因,希望从繁杂的资料中总结真正有用的知识(当然也希望能帮助到你)。我觉得WebGL是学习OpenGL系列三维图形渲染技术很好的入门点。WebGL是OpenGL的浏览器版本,基本上可以认为是OpenGL的子集,能被WebGL保留而不剔除的技术,必须是三维图形渲染技术的精华。在这里给大家强烈推荐《WebGL编程指南》这本书,我这篇教程正是在这本书的基础之上总结出来的。

在学习OpenGL/WebGL的时候,我还感觉到很多资料举得例子往往都太简单了,确实是一看就懂,但是在实际遇到的问题的时候却往往解决不了。我还是认为在实际中解决问题,更能加深对知识的理解。正好最近我在研究GIS中地形的绘制,那么我就通过一步一步绘制地形的示例,来总结WebGL的相关知识。如果你不懂GIS这些术语也不要紧,只需要知道我这里的最终目的是想绘制的是一个大地高程模型,是一个包含XYZ坐标的点集,表达了地形的情况。

2. 示例:绘制一个点

编写WebGL程序跟编写Web前端程序的步骤是一样的,包含HTML和JavaScript两个部分,通过浏览器进行调试。

1) HelloPoint1.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><title>Draw a point (1)</title></head><body onload="main()"><canvas id="webgl" width="400" height="400">Please use a browser that supports "canvas"</canvas><script src="../lib/webgl-utils.js"></script><script src="../lib/webgl-debug.js"></script><script src="../lib/cuon-utils.js"></script><script src="HelloPoint1.js"></script></body>
</html>

这一段HTML非常简单,从实际表现上来说就是创建了一个画布<canvas>。<canvas>是HTML5引入的的一个绘制标签,可以在画布中绘制任意图形。WebGL正是通过<canvas>元素进行绘制的。
除此之外,这段代码还通过<script>标签引入了几个外部JS文件。其中lib目录中的几个JS文件是一些通用的组件(来自《WebGL编程指南》的源码),可以先暂时不用关心其具体实现;最后一个导入的HelloPoint1.js正是我们编写的绘制模块。而在<body>标签中定义的onload事件属性绑定的正是HelloPoint1.js中的main()函数。

2) HelloPoint1.js

// 顶点着色器程序
var VSHADER_SOURCE = 'void main() {\n' +'  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // Set the vertex coordinates of the point'  gl_PointSize = 10.0;\n' +                    // Set the point size'}\n';// 片元着色器程序
var FSHADER_SOURCE ='void main() {\n' +'  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // Set the point color'}\n';function main() {// 获取 <canvas> 元素var canvas = document.getElementById('webgl');// 获取WebGL渲染上下文var gl = getWebGLContext(canvas);if (!gl) {console.log('Failed to get the rendering context for WebGL');return;}// 初始化着色器if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// 指定清空<canvas>的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 清空<canvas>gl.clear(gl.COLOR_BUFFER_BIT);// 绘制一个点gl.drawArrays(gl.POINTS, 0, 1);
}

这段JS代码的主要内容就是前面提到的main函数,一旦HTML被浏览器加载成功,这段脚本就会执行。在main函数中主要有一下几步:

(1) 准备工作

document.getElementById(‘webgl’):文档对象模型DOM的函数,获取到HTML页面的元素。

getWebGLContext(canvas):获取WebGL渲染上下文,保存在gl变量中。因为不同浏览器获取函数不太一样,所以通过组件cuon-utils提供的函数来统一行为。

(2) 着色器

initShaders:初始化着色器。

首先要知道什么是着色器。如果你只学习过固定管线或者其他的二维绘图组件(如GDI),就会非常困惑着色器是什么,为什么要用着色器。比如说在固定管线中,绘制点就是drawPoint,绘制线就drawLine。而在WebGL中,绘制工作则主要被分解成顶点着色器和片元着色器两个步骤了。

在启动JS程序后,绘制工作首先进入的是顶点着色器,在顶点着色器中描述顶点特性(如位置、颜色等),顶点就是三维空间的点,比如三角形的三个顶点;然后进入到片元着色器,在片元着色器中逐片元处理像素(如光照、阴影、遮挡)。最后片元传入到颜色缓冲区,进行显示。渲染过程如下:

这个过程是一个类似水流的流向过程,所以这个过程被称为渲染管线(Pipeline)。并且,这个过程是需要我们去编程控制的,比如观察者的视角变化需要在顶点着色器去调控;光线对颜色的变化需要在片元着色器去调控等;因此,这个过程就是可编程管线。通过着色器程序,三维图像渲染就更加的灵活强大。

在initShaders()函数中,传入了预先定义的JS字符串VSHADER_SOURCE和FSHADER_SOURCE。需要说明是,着色器程序是以字符串的形式嵌入到JS文件中运行的。这个函数同样是cuon-utils组件提供的,调用之后就告诉WebGL系统着色器已经建立好了并可以随时使用。

(3) 顶点着色器

顶点着色器的定义如下:

// 顶点着色器程序
var VSHADER_SOURCE = 'void main() {\n' +'  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // Set the vertex coordinates of the point'  gl_PointSize = 10.0;\n' +                    // Set the point size'}\n';

前面说到顶点着色器程序是嵌入在JS中的程序,所以虽然传入的是字符串,但其实本质是着色器描述语言(GLSL:OpenGL Shading Language)。既然是语言也就有自己的函数与变量定义。main()函数是每个着色器程序定义的入口。在main函数中,将顶点的坐标赋值给内置变量gl_Position,点的尺寸赋值给内置变量gl_PointSize。

注意这里的gl_Position是必须赋值的,否则着色器不会正常工作。赋值的类型是vec4,也就是一个四维矢量。一般来说,描述点位只需要三维矢量就可以了,但是很多情况下需要四个分量的齐次坐标。齐次坐标(x,y,z,w)等价于三维坐标(x/w,y/w,z/w)。所以如果第四个分量是1,那么就是普通的三维坐标;如果第四分量为0,就表示无穷远的点。

(4) 片元着色器

片元着色器的定义如下:

// 片元着色器程序
var FSHADER_SOURCE ='void main() {\n' +'  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // Set the point color'}\n';

如同顶点着色器一样,片元着色器将点的颜色赋值给gl_FragColor变量,gl_FragColor是片元着色器唯一的内置变量,控制像素在屏幕上的最终颜色。

(5) 清空缓冲区

gl.clearColor():设置清空的背景色。
gl.clear(gl.COLOR_BUFFER_BIT): 清空颜色缓冲区。

(6) 绘制操作

gl.drawArrays(gl.POINTS, 0, 1):绘制一个点。
顶点着色器只是指定了绘制的顶点,还需要指定顶点到底成点、成线还是成面,gl.drawArrays()就是这样一个函数,这里告诉WebGL系统应该绘制一个点。

3. 结果

最终的运行结果很简单,在Chrome打开HelloPoint1.html,页面显示了一个绘制一个点的窗口:

4. 参考

本来部分代码和插图来自《WebGL编程指南》。

代码和数据地址

上一篇
目录
下一篇

WebGL简易教程(一):第一个简单示例相关推荐

  1. WebGL简易教程——目录

    文章目录 1. 绪论 2. 目录 3. 资源 1. 绪论 最近研究WebGL,看了<WebGL编程指南>这本书,结合自己的专业知识写的一系列教程.之前在看OpenGL/WebGL的时候总是 ...

  2. WebGL简易教程(十四):阴影

    文章目录 1. 概述 2. 示例 2.1. 着色器部分 2.1.1. 帧缓存着色器 2.1.2. 颜色缓存着色器 2.2. 绘制部分 2.2.1. 整体结构 2.2.2. 具体改动 2.2.2.1. ...

  3. WebGL简易教程(十五):加载gltf模型

    文章目录 1. 概述 2. 实例 2.1. 数据 2.2. 程序 2.2.1. 文件读取 2.2.2. glTF格式解析 2.2.2.1. 场景节点 2.2.2.2. 网格 2.2.2.3. 缓冲,缓 ...

  4. WebGL简易教程(十一):纹理

    文章目录 1. 概述 2. 实例 2.1. 准备纹理 2.2. 配置纹理 2.3. 使用纹理 3. 结果 4. 参考 1. 概述 在之前的之前的教程<WebGL简易教程(九):综合实例:地形的绘 ...

  5. WebGL简易教程(十):光照

    目录 1. 概述 2. 原理 2.1. 光源类型 2.2. 反射类型 2.2.1. 环境反射(enviroment/ambient reflection) 2.2.2. 漫反射(diffuse ref ...

  6. NBear.Mapping使用教程(3):第一个简单例子

    不断有朋友希望能提供一些示例,同时我也发现,单纯发一些文字性的教程.大家好像都没有看明白NBear.Mapping是干嘛用的,所以从这篇开始我会陆续以实例的方式介绍NBear.Mapping的使用,以 ...

  7. WebGL简易教程(五):图形变换(模型、视图、投影变换)

    文章目录 1. 概述 2. 详论 1) 模型变换 (1) 平移变换 (2) 缩放变换 (3) 旋转变换 (4) 组合变换 2) 视图变换 (1) 原理 (2) 推导 3) 投影变换 (1) 透视投影 ...

  8. SpringBoot入门第一个简单示例

    2019独角兽企业重金招聘Python工程师标准>>> 本示例使用SpringBoot官方的QuickStart程序 详情地址:http://projects.spring.io/s ...

  9. mayapython开关_Maya Python 简易教程.doc

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspPython Maya Python 简易教程.doc25页 本 ...

最新文章

  1. 典型问题分析(十五)
  2. Day3--js--可恶之变量声明提升大法.。。
  3. Servlet Cookie处理
  4. python读excel字体颜色_python 设置 excel 单元格颜色填充和字体效果
  5. elasticSearch6源码分析(4)indices模块
  6. RabbitMQ整合SpringBoot(web)
  7. Django框架(16.Django中的模型类管理器以及自定义管理器)
  8. php实现数字滚动效果,vue如何实现数字滚动增加效果?代码示例
  9. Ubuntu 20.04 linux系统安装docker
  10. 快速排序——三种划分方式
  11. 2007年7月23日旅游
  12. 两种通用型测试用例模板(excel/xmind)
  13. 软件录制电脑扬声器音频的原理
  14. win10豆沙绿设置
  15. mysql 联合主键 null_MySQL联合主键的索引使用
  16. 实现进程互斥需要遵循的原则
  17. A recap of native memory
  18. 智能车图像处理逆透视教程
  19. bean是什么,bean和javabean
  20. 检测恶意软件分类模型中的概念漂移

热门文章

  1. 抓实“链长制”,维护产业链稳定,推进产业链纵深拓展和升级再造
  2. scud的jvalidation
  3. ios safari 模拟器_iOS开发之Safari调试WebView页面
  4. [Andriod] - Andriod Studio + 逍遥模拟器
  5. 初次使用SpiderMonkey
  6. Android source code gerrit
  7. 【存储】RAID 技术介绍和总结
  8. 2016计算机应用能力,2016全国专业技术人员计算机应用能力考试.doc
  9. Mplayer播放没有声音
  10. R语言的四种数据结构---数据框