注:文章译自http://wgld.org/。原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:]。另外。鄙人webgl研究还不够深入。一些专业词语。假设翻译有误。欢迎大家指正。

本次的demo的执行结果

添加顶点属性的个数

上次,最终绘制了一个三角形。可是仅仅绘制了一个纯白色的多边形。

这次。给多边形的顶点中加入颜色属性,基本上做的事情和上一篇文章一样,仅仅是略微添加点步骤而已。

首先,就像曾经多次反复的那样,顶点能够包括非常多种情报(參考:顶点缓存和基础)。并且每个情报叫做一个顶点属性。

上一篇的demo,顶点种仅仅包括了位置情报这一个顶点属性,这一次加入一个颜色的顶点属性。
一个顶点属性。须要有一个东西和它相应,还记得吧。

答案就是,顶点缓存(VBO)。上一篇中准备了保存位置用的VBO进行渲染,这次再准备还有一个VBO,同一时候将位置情报的VBO和颜色情报的VBO都传给顶点着色器。来给多边形着色。

着色器代码的改动

那么,先从着色器的代码開始看吧。
这次,须要两个attribute变量。各自是为了接收顶点的位置和颜色。
>顶点着色器的代码

attribute vec3 position;
attribute vec4 color;
uniform mat4 mvpMatrix;
varying vec4 vColor; void main(void){
vColor = color;
gl_Position = mvpMatrix * vec4(position, 1.0);
}

能够看到,一同声明了两个attribute变量。position和上次一样,没有变化,在它以下多了一个color,是为了处理顶点的颜色。
而上一篇中没有出现的varying变量。这一次也出现了。

就当作是复习了,再简单说一下,varying变量是顶点着色器和片段着色器之间的桥梁。看一下main函数中的代码就知道了,仅仅须要将attribute变量中的顶点的颜色直接赋值给varying变量。

加了这个处理之后,顶点着色器中的顶点属性就能传给片段着色器了。当然。顶点着色器中不须要做不论什么处理就能将数据传给片段着色器,这也是可编辑渲染管线的长处之中的一个。
接着,看片段着色器。
>片段着色器的代码

precision mediump float;
varying vec4 vColor;
void main(void){
gl_FragColor = vColor;
}

上一篇中使用的片段着色器,直接将颜色数据代入到了中的gl_FragColor中,所以绘制出的三角形是单色的。这一次,使用从顶点着色器传来的varying类型的变量vColor,那么顶点的颜色属性就会对多边形产生影响。

*尽管说顶点着色器和片段着色器中都使用了相同的名字的varying变量,可是事实上是两个全然不同的变量。

>>指定准确度的precision

这一次的片段着色器中的第一行。出现了一个陌生的precision,这个precision是用来指定数值的准确度的keyword。紧接着跟在precision后面的是准确度修饰符。
这个修饰符有三种,简单点说就是指定准确度为上。中,下。事实上。变量中使用的小数发生变化时(也就是说。处理的数值的位数添加或是降低),依据执行的环境不同得到的结果是不太统一的。
lowp   :准确度低
mediump:准确度中
highp  :准确度高
上面的片段着色器代码中,precision后面紧接着写的是mediump float,这是说。让片段着色器中的float类型的数值的准确度都依照mediump来用。
无论在片段着色器中有没有做什么特殊的处理。首先要将precision相关的设定写上,否则在编译着色器的时候会出错。

这就像魔法的咒语一样,逃不掉的。

顶点缓存相关的处理

着色器之后。该是VBO了。这里尽管添加了一些内容,事实上仅仅是相同的东西做了两次,细致看的话,就会明确过来。跟上次基本上没什么变化吧。
>顶点数据的矩阵的做成

// 从数组中获取attributeLocation
var attLocation = new Array(2);
attLocation[0] = gl.getAttribLocation(prg, 'position');
attLocation[1] = gl.getAttribLocation(prg, 'color'); // 将元素数attribute保存到数组中
var attStride = new Array(2);
attStride[0] = 3;
attStride[1] = 4; // 保存顶点的位置情报的数组
var vertex_position = [
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
]; // 保存顶点的颜色情报的数组
var vertex_color = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];

上次的顶点属性仅仅有一个。所以保存顶点属性的序号的是一个纯粹的变量。这次,顶点属性有两个,所以使用了数组。而颜色是由RGBA四个元素组成的,所以颜色情报的数组长度为[顶点数 x 4]。
将顶点数据保存到数组之后,下一步就是依据数组来生成VBO了。

以下是代码。
>依据顶点数据数组生成VBO

// 生成VBO
var position_vbo = create_vbo(vertex_position);
var color_vbo = create_vbo(vertex_color); // VBO绑定(位置情报)
gl.bindBuffer(gl.ARRAY_BUFFER, position_vbo);
gl.enableVertexAttribArray(attLocation[0]);
gl.vertexAttribPointer(attLocation[0], attStride[0], gl.FLOAT, false, 0, 0); // VBO绑定(颜色情报)
gl.bindBuffer(gl.ARRAY_BUFFER, color_vbo);
gl.enableVertexAttribArray(attLocation[1]);
gl.vertexAttribPointer(attLocation[1], attStride[1], gl.FLOAT, false, 0, 0);

生成VBO之后。进行绑定,写入数据等处理,位置情报和颜色情报都是相同的,所以是反复了两次相同的处理。有人看到这里可能会有些想法了。VBO周围的处理,能够直接做成一个函数,将数组当作參数传进来基本上就攻克了。

总结

以上,就是与上一篇的内容相比的变更点。

主要就是着色器和VBO周围的处理有了些小变化。假设再给顶点添加其它新的属性的话,就依葫芦画瓢。像本次的内容一样。依照相同的步骤。再反复一遍就能够了,这样就能够给顶点自由的加入属性了。

最后,贴出本篇文章的demo的所有代码,链接也在最后给出,大家能够參考一下。

下次,通过操作模型变换矩阵,来绘制多个模型。

>demo的HTML代码

<html>
<head>
<title>WebGL TEST</title>
<script src="script.js" type="text/javascript"></script>
<script src="minMatrix.js" type="text/javascript"></script> <script id="vs" type="x-shader/x-vertex">
attribute vec3 position;
attribute vec4 color;
uniform mat4 mvpMatrix;
varying vec4 vColor; void main(void){
vColor = color;
gl_Position = mvpMatrix * vec4(position, 1.0);
}
</script> <script id="fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor; void main(void){
gl_FragColor = vColor;
}
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

>demo的javascript代码

onload = function(){
// canvas对象获取
var c = document.getElementById('canvas');
c.width = 300;
c.height = 300; // webgl的context获取
var gl = c.getContext('webgl') || c.getContext('experimental-webgl'); // 设定canvas初始化的颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0); // 设定canvas初始化时候的深度
gl.clearDepth(1.0); // canvas的初始化
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // 顶点着色器和片段着色器的生成
var v_shader = create_shader('vs');
var f_shader = create_shader('fs'); // 程序对象的生成和连接
var prg = create_program(v_shader, f_shader); // attributeLocation的获取
var attLocation = new Array(2);
attLocation[0] = gl.getAttribLocation(prg, 'position');
attLocation[1] = gl.getAttribLocation(prg, 'color'); // 将元素数attribute保存到数组中
var attStride = new Array(2);
attStride[0] = 3;
attStride[1] = 4; // 保存顶点的位置情报的数组
var vertex_position = [
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
]; // 保存顶点的颜色情报的数组
var vertex_color = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
]; // 生成VBO
var position_vbo = create_vbo(vertex_position);
var color_vbo = create_vbo(vertex_color); // VBO绑定(位置情报)
gl.bindBuffer(gl.ARRAY_BUFFER, position_vbo);
gl.enableVertexAttribArray(attLocation[0]);
gl.vertexAttribPointer(attLocation[0], attStride[0], gl.FLOAT, false, 0, 0); // VBO绑定(颜色情报)
gl.bindBuffer(gl.ARRAY_BUFFER, color_vbo);
gl.enableVertexAttribArray(attLocation[1]);
gl.vertexAttribPointer(attLocation[1], attStride[1], gl.FLOAT, false, 0, 0); // 使用minMatrix.js对矩阵的相关处理
// matIV对象生成
var m = new matIV(); // 各种矩阵的生成和初始化
var mMatrix = m.identity(m.create());
var vMatrix = m.identity(m.create());
var pMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create()); // 视图变换坐标矩阵
m.lookAt([0.0, 1.0, 3.0], [0, 0, 0], [0, 1, 0], vMatrix); // 投影坐标变换矩阵
m.perspective(90, c.width / c.height, 0.1, 100, pMatrix); // 各矩阵想成,得到最终的坐标变换矩阵
m.multiply(pMatrix, vMatrix, mvpMatrix);
m.multiply(mvpMatrix, mMatrix, mvpMatrix); // uniformLocation的获取
var uniLocation = gl.getUniformLocation(prg, 'mvpMatrix'); // 向uniformLocation中传入坐标变换矩阵
gl.uniformMatrix4fv(uniLocation, false, mvpMatrix); // 绘制模型
gl.drawArrays(gl.TRIANGLES, 0, 3); // context的刷新
gl.flush(); // 生成着色器的函数
function create_shader(id){
// 用来保存着色器的变量
var shader; // 依据id从HTML中获取指定的script标签
var scriptElement = document.getElementById(id); // 假设指定的script标签不存在。则返回
if(!scriptElement){return;} // 推断script标签的type属性
switch(scriptElement.type){ // 顶点着色器的时候
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);
break; // 片段着色器的时候
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);
break;
default :
return;
} // 将标签中的代码分配给生成的着色器
gl.shaderSource(shader, scriptElement.text); // 编译着色器
gl.compileShader(shader); // 推断一下着色器是否编译成功
if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){ // 编译成功,则返回着色器
return shader;
}else{ // 编译失败,弹出错误消息
alert(gl.getShaderInfoLog(shader));
}
} // 程序对象的生成和着色器连接的函数
function create_program(vs, fs){
// 程序对象的生成
var program = gl.createProgram(); // 向程序对象里分配着色器
gl.attachShader(program, vs);
gl.attachShader(program, fs); // 将着色器连接
gl.linkProgram(program); // 推断着色器的连接是否成功
if(gl.getProgramParameter(program, gl.LINK_STATUS)){ // 成功的话,将程序对象设置为有效
gl.useProgram(program); // 返回程序对象
return program;
}else{ // 假设失败,弹出错误信息
alert(gl.getProgramInfoLog(program));
}
} // 生成VBO的函数
function create_vbo(data){
// 生成缓存对象
var vbo = gl.createBuffer(); // 绑定缓存
gl.bindBuffer(gl.ARRAY_BUFFER, vbo); // 向缓存中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW); // 将绑定的缓存设为无效
gl.bindBuffer(gl.ARRAY_BUFFER, null); // 返回生成的VBO
return vbo;
} };

给顶点加入颜色,然后绘制三角形的demo

http://wgld.org/s/sample_003/

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)的更多相关文章

  1. [WebGL入门]十二,模型数据和顶点属性

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外.鄙人webgl研究还不够深入,一些专业词语.假设翻译有误.欢迎大家指 ...

  2. [WebGL入门]十四,绘制多边形

    注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外,鄙人webgl研究还不够深入.一些专业词语,假设翻译有误,欢迎大家 ...

  3. WebGL入门教程(五)-webgl纹理

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 WebGL入门教程(四)-webgl颜色 这里就需要用到 ...

  4. [WebGL入门]十六,绘制多个模型

    注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入.一些专业词语.假设翻译有误.欢迎大家 ...

  5. [WebGL入门]十八,利用索引缓存来画图

    注:文章译自http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:].另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...

  6. [WebGL入门]十九,遮挡剔除和深度測试

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误.欢迎大家指 ...

  7. [WebGL入门]十,矩阵计算和外部库

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...

  8. Android入门(十五)通知

    原文链接:http://www.orlion.ga/663/ 1.通知的基本用法 创建通知的步骤,首先需要一个NotificationManager来对通知进行管理,可以调用Context的getSy ...

  9. Spring入门(十五):使用Spring JDBC操作数据库

    在本系列的之前博客中,我们从没有讲解过操作数据库的方法,但是在实际的工作中,几乎所有的系统都离不开数据的持久化,所以掌握操作数据库的使用方法就非常重要. 在Spring中,操作数据库有很多种方法,我们 ...

随机推荐

  1. 洛谷 P1313 计算系数 (二项式定理)

    这道题正好复习了二项式定理 所以答案就是a^n * b^m * c(n, k) 然后注意一些细节 我一开始写组合数只写一行的组合数 即c[0] = 1; c[i] = c[i-1] * (n - i ...

  2. 【【henuacm2016级暑期训练】动态规划专题 J】Red-Green Towers

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 显然最多1000行的样子. 从上到小做dp 设f[i][j]为前i行,使用了j个红色方块的方案数. f[1][r] = 1;如果r& ...

  3. Android 混淆后的代码调试

    ProGuard的输出文件及用处 混淆之后,会给我们输出一些文件,在gradle方式下是在<project_dir>/build/proguard/目录下,ant是在<project ...

  4. POSIX 线程编程(一)简介

    简介 在共享内存的多处理器结构中,可以用线程来实现并行.对于UNIX系统, IEEE POSIX 1003.1c标准规定了C语言线程编程接口的标准.这份标准的实现就是POSIX threads, 或者 ...

  5. [Angular] Provide Feedback to Progress Events with Angular’s HttpRequest Object

    In some cases your application might need to upload large amounts of data, such as files. Obviously ...

  6. LA 6437 Power Plant (prim最小生成树)

    还是裸的最小生成树 #include<bits/stdc++.h> using namespace std; int T,N,M,P,K,a,b,c; int dist[1020],m[1 ...

  7. Oracle RAC 实施

    第 1 步 — 确定项目范围 理由 我们实施 Oracle RAC 是为了使我们的应用程序可伸缩和高度可用,以及为我们的客户提供更可靠的服务. 目标/可交付产品 该项目的最终产品将是一个新的 Orac ...

  8. Redis 安装与简单示例 <第一篇>【转】

    一.Redis的安装 Redis下载地址如下:https://github.com/dmajkic/redis/downloads 解压后根据自己机器的实际情况选择32位或者64位.下载解压后图片如下 ...

  9. MySQL日期数据类型和时间类型使用总结

    转自: http://blog.chinaunix.net/space.php?uid=11327712&do=blog&id=32416 MySQL 日期类型:日期格式.所占存储空间 ...

  10. SharePoint 使用Expression Web 设计网站

    创建好网站以后可就可以开始发布了 possible causes : 1.The web server may not hava the FrontPage Server Extensions ins ...