注:文章译自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. linux下为firfox安装flash player

    1.去官网下载×.tar.gz包,如:flash_player_npapi_linux.x86_64.tar.gz 2.解压 tar -zxvf flash_player_npapi_linux.x8 ...

  2. 论文阅读《End-to-End Learning of Geometry and Context for Deep Stereo Regression》

    端到端学习几何和背景的深度立体回归 摘要     本文提出一种新型的深度学习网络,用于从一对矫正过的立体图像回归得到其对应的视差图.我们利用问题(对象)的几何知识,形成一个使用深度特征表示的代价量(c ...

  3. AsyncTask 简要介绍

    当Android的UI线程超过5s未响应时,系统会引发ANR(Application Not Responding)异常,所以一般不在UI线程中执行耗时任务.一般是在其他线程中处理耗时任务,然后及时更 ...

  4. 监控aps.net计数器

  5. HDU 4312 Contest 2

    题目要求两点间的最大值作为距离即: 即是切比雪夫距离.而切比雪夫距离与曼哈顿距离的转换却很巧妙. 把平面坐标所有点绕原点逆向旋转45度后,所得点的曼哈顿距离之和除以√2,即是切雪比夫距离.旋转点的公式 ...

  6. jsoup抓取网页+具体解说

    jsoup抓取网页+具体解说 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目.我以前在 IBM DW 上发表过两篇关于 htmlparser 的文章.各自 ...

  7. HDU 5305 Friends (搜索+剪枝) 2015多校联合第二场

    開始对点搜索,直接写乱了.想了想对边搜索,尽管复杂度高.剪枝一下水过去了. 代码: #include<cstdio> #include<iostream> #include&l ...

  8. LIVE555研究之五:RTPServer(二)

    port是一样的. DynamicRTSPServer 继承关系: Medium是非常多类的基类.内部定义了指向环境类的引用和一个char类型媒体名称.并定义了依照媒体名称,查找相应媒体的成员函数lo ...

  9. Session小案例-----简单购物车的使用

    Session小案例-----简单购物车的使用 同上篇一样,这里的处理请求和页面显示相同用的都是servlet. 功能实现例如以下: 1,显示站点的全部商品 2.用户点击购买后,可以记住用户选择的商品 ...

  10. EF的CRUD

    已经知道EF就是一个能够使得编程人员用面向对象的思想操作数据库的框架,那么在最初学习SQL的时候我们就知道对数据库的操作就是增删改查.万变不离其宗. EF也是操作数据库的当然也就是要对数据库实现增删改 ...