webgl自学笔记——几何图形
3D应用的基础元素:
1、canvas,它是渲染场景的占位符。标准html的canvas元素
2、Objects,这里指的是组成一个场景的所有3d实体。这些实体都由三角形组成。webgl中使用Buffer(vertex、index)来存储管理这些3d实体数据。
3、Lights,如果没有光照3d场景将看不到任何东西。webgl使用着色器来为场景中的光照建模。我们将会看到3d实体如何根据物理规律来反射和吸收光照,并讨论不同的光照模型。
4、Camera,摄像机作为3d世界的视口。我们通过摄像机来开发和看到一个3d场景。我们要理解如何根据不同的场景来使用不同的矩阵操作,这些操作可以利用相机原理来建模。
webgl中的数据类型:
webgl对图形有一种标准的处理方式,与我们拥有的表面的复杂性和顶点个数无关。只有两种基础的数据类型来表达3d物体的几何形状:vertices和indices(顶点和索引)。
Vertices: 代表3d物体的拐点,每一个顶点使用3个数字来表达想x,y,z;webgl中没有提供api来将独立的顶点传递到渲染管线中,因此我们需要将所有的顶点放在一个JavaScript数组中然后通过这个数组来构造一个webgl顶点缓冲区(vertex buffer)。
Indices: 索引是在一个给定3d场景的中的所有顶点的数字标识。索引告诉webgl如何有序的来链接顶点来生成一个表面。像顶点一样,索引也是存储在JavaScript数组中然后使用webgl索引缓冲区传递给webgl的渲染管线。
有两种webgl 缓冲区来描述和处理几何图形:
包含顶点数据的缓冲区:Vertex Buffer Objects(VBO)
包含索引数据的缓冲区:Index Buffer Objects(IBO)
webgl的渲染管线:

Vertex Buffer Objects
VBO包含了webgl要求来描述将要渲染的几何图形的数据。除了上面提到的顶点坐标外,还有vertex normal(顶点法线),颜色、纹理坐标等都可以用vbo来建模。
Vertex shader
顶点着色器将会来每个顶点上被调用,顶点着色器将用来操作之前的顶点数据,如顶点坐标、法线、颜色、文理坐标。这些数据将被顶点着色器内置的attributes变量来引用,每一个attribute指向一个他读取顶点数据的VBO。
Fragment shader
每三个顶点定义了一个三角形在三角形表面的每一个元素都需要被分配一个颜色,否则我们的表面将是透明的。
三角形表面的每一个元素成为一个片元(fragment)。因为我们处理的表面将被呈现在我们屏幕上,所以片元通常被理解为像素。
片元着色器的主要目的是为表面的每个独立像素来计算颜色。

Framebuffer
它是包含一个之前被片元着色器处理的片元二维的缓冲区。一旦所有的片元都被处理过后,一张二维图片将被构造并显示在屏幕上。framebuffer是渲染管道的最终点。
Attributes,uniforms,varyings是着色器编程中经常用到的三种类型的变量。
Attributes是顶点着色器中的输入变量,如顶点坐标、顶点颜色等。由于顶点着色器将会在每个顶点上都被调用,所以每次顶点着色器被调用时的输入变量attributes都是不同的。
Uniforms 是在顶点着色器和片元着色器中都能被使用的输入变量。在一个渲染循环中unifroms通常是不变的常量。如灯源位置。
Varyings用来由顶点着色器向片元着色器传递数据。
1、webgl缓冲区数据处理流程:
ver vertices = [];
var myBuffer = gl.createBuffer(); // 创建缓冲区
// 绑定缓冲区; 由于webgl是一个状态机,一旦绑定buffer,之后所有的缓冲操作都将在绑定的buffer上执行,直到解绑这个buffer或者绑定到另一个buffer上。
gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer);
// 绑定缓冲区后我们需要为他分配内容,webgl不能直接使用JavaScript数组,而是使用类型数组,以便缓冲区对象能够使用原生二进制数据来加快图形处理速度。
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);// 清空缓存
2、将attributes连接到VBOs
VBO创建后,我们需要将这些缓冲区链接到顶点着色器的属性中。每一个顶点着色器的attribute将且仅将指向一个缓冲区对象。
通常来讲我们有以下对应关系。

缓冲区数据进入顶点着色器分为三步:
1)绑定一个缓冲区:gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer)
2 ) 将一个attribute指向刚刚绑定的VBO:gl.vertexAttribPointer(Index, Size, Type, Norm, Stride, Offset);(该函数定义了一个从当前绑定缓冲区读取信息的指针;参数Index指的是将被匹配缓冲区的attribute的索引)
3)激活attribute:gl.enableVertexAttribArray(aVertexPosition)
下面的图表记录了匹配过程

3、渲染
定义完VBO对象并绑定到顶点着色器属性后,就可以准备渲染了。完成渲染过程我们可以使用两个API函数:drawArrays、drawElements
这两个方法都是用来像帧缓冲区中写入数据;drawArrays按照在缓冲区中的顶点数据的顺序来创建图形,相反drawElements使用索引来访问顶点缓冲区中的数据来创建图形。
drawArrays和drawElements仅接受 enabled arrays ,他们是被匹配到激活的顶点着色器attribute的vbo对象。
当索引信息无法获得时,我们使用drawArrays方法。在大多数情况下当几何图形很简单以至于定义索引是浪费资源时我们使用drawArrays方法,比如三角形、矩形。

使用drawArrays只适合非常简单的图形,如果是连续三角形,那么vbo中需要重复定义每个顶点,并且这些点都会在顶点着色器中被处理,浪费空间和性能。
gl.drawArrays(Mode, First, Count)
drawElements允许使用IBO来告诉浏览器如何去渲染图形。因为有了索引VBO中的数据不用像之前一样被重复定义,只需要定义一次,但可以通过索引来多次使用。这种方式减少内存和GPU的性能损耗。

使用drawElements至少需要两个Buffer:VBO和IBO;顶点着色器将在每一个VBO的顶点上执行,然后渲染管线使用IBO将几何图形聚集成三角形。(确保VBO、IBO都被绑定过)
gl.drawElements(Mode, Count, Type, Offset)
webgl作为一个状态机的buffer控制
我们可以拿到一些关于渲染管线状态的信息,比如:
getParameter(type)
ARRAY_BUFFER_BINDING取得一份关于最近绑定的VBO的引用
ELEMENT_ARRAY_BUFFER取得一份关于最近绑定的IBO的引用
getBufferParameter(type, parameter)
type: ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER
parameter: BUFFER_SIZE, BUFFER_USAGE
isBuffer(object)
基本步骤:
initProgram()
initBuffers()
drawSence()
创建着色器三步骤:
var shader = gl.createShader();
gl.shaderSource(shader, source);
gl.compileShader(shader);
gl.getShaderParameter(shader, gl.COMPILE\_STATUS);
initProgram步骤:
prg = gl.createProgram();
gl.attachShader(prg, shader); // vs fs
gl.linkProgram(prg);
gl.getProgramParameter(prg, gl.LINK\_STATUS)
gl.useProgram(prg);
prg.aVertexPosition = gl.getAttribLocation(prg, 'aVertexPosition');
webgl自学笔记——几何图形的更多相关文章
- webgl自学笔记——光照
在Webgl中我们使用顶点着色器和片元着色器来为我们的场景创建光照模型.着色器允许我们使用数学模型来控制如何照亮我们的场景. 最好有线性代数的相关知识. 本章中: 光源.法线.材料 光照和着色的区别 ...
- webgl自学笔记——矩阵变换
这章主要探讨矩阵,这些矩阵代表了应用在我们场景上的变换,允许我们移动物体.然而在webGL api中并没有一个专门的camera对象,只有矩阵.好消息是使用矩阵来取代相机对象能让webgl在很多复杂动 ...
- webgl自学笔记——深度监测与混合
这一章中关于webgl中颜色的使用我们将深入研究.我们将从研究颜色在webgl和essl中如何被组装和获取开始.然后我们讨论在物体.光照和场景中颜色的使用.这之后我们将看到当一个物体在另一个物体前面是 ...
- 《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第四章自学笔记 进程调度 By20135203齐岳 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵 ...
- 《Linux内核设计与实现》课本第三章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第三章自学笔记 进程管理 By20135203齐岳 进程 进程:处于执行期的程序.包括代码段和打开的文件.挂起的信号.内核内部数据.处理器状态一个或多个具有 ...
- 《Linux内核设计与实现》课本第十八章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第十八章自学笔记 By20135203齐岳 通过打印来调试 printk()是内核提供的格式化打印函数,除了和C库提供的printf()函数功能相同外还有一 ...
- python自学笔记
python自学笔记 python自学笔记 1.输出 2.输入 3.零碎 4.数据结构 4.1 list 类比于java中的数组 4.2 tuple 元祖 5.条件判断和循环 5.1 条件判断 5.2 ...
- ssh自学笔记
Ssh自学笔记 Ssh简介 传统的网络服务程序,如:ftp.pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用心的人非常容易就可以截获这些口令和数据.而且,这些服务 ...
- JavaScript高级程序设计之自学笔记(一)————Array类型
以下为自学笔记. 一.Array类型 创建数组的基本方式有两种: 1.1第一种是使用Array构造函数(可省略new操作符). 1.2第二种是使用数组字面量表示法. 二.数组的访问 2.1访问方法 在 ...
随机推荐
- R绘图字体解决方案(转)
COS论坛里面经常会遇到的一个问题就是绘图时中文字体怎么解决.最初,一个流行的方法是使用family = "GB1",但一般这样做出来的图比较难看,而且并没有完全解决问题.后来发现 ...
- RabbitMQ系列教程之一:我们从最简单的事情开始!Hello World
一.简介 RabbitMQ是一个消息的代理器,用于接收和发送消息,你可以这样想,他就是一个邮局,当您把需要寄送的邮件投递到邮筒之时,你可以确定的是邮递员先生肯定会把邮件发送到需要接收邮件的人 ...
- GPU编程--kernels(2)
"如何区分不同的数据单位单位呢?" "如何确定程序是在CPU端执行,还是GPU端执行呢?" "如何确定要调用的GPU线程数呢?" 下面举一个 ...
- 再来写一个随机数解决方案,对Random再来一次封装
本文提供对Random的封装,简化并扩展了其功能 获取随机数,确保同时调用不会重复 //new Random().Next(5); RandomTask.Next(); 从一个列表中,随机获取其中某个 ...
- Cordova各个插件使用介绍系列(二)—$cordovaBarcodeScanner扫描二维码与生成二维码
详情链接地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-2-cordovabarcodescanner/ 这是 ...
- 推荐几个Dynamic Crm的大神博客
ghostbear的博客:http://blog.csdn.net/ghostbear/article/category/1072859 ghostbear大神的博客是新手学习Dynamics Crm ...
- [USACO09MAR]地震损失2Earthquake Damage 2
地震破坏 时间限制: 1 Sec 内存限制: 128 MB 题目描述 威斯康星发生了一场地震!约翰的牧场遭到了打击,有一些牛棚变成了废墟,如果一间牛棚遭到 了破坏,那么所有和它相连的道路都不能使用了 ...
- 使用CoApp创建NuGet C++静态库包
NuGet是微软开发平台下的包管理软件,使用它你可以非常方便的将一些第三方的库.框架整合进自己的项目中,省去了不少麻烦的配置过程.但是从官方文档上来看,貌似NuGet对C++的支持不是很好,并且在现阶 ...
- 基于TFS的.net技术路线的云平台DevOps实践
DevOps是近几年非常流行的系统研发管理模式,很多公司都或多或少在践行DevOps.那么,今天就说说特来电云平台在DevOps方面的实践吧. 说DevOps,不得不说DevOps的具体含义.那么,D ...
- php添加pcntl扩展(Linux)
pcntl扩展可以支持php的多线程操作(仅限linux)原本需要重新编译PHP的后面configrue提示加上--enable-pcntl 由于我的php是采用yum安装的,所以不能采用上面的方式下 ...