[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)
注:文章译自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后面的是准确度修饰符。 这就像魔法的咒语一样,逃不掉的。 |
顶点缓存相关的处理
着色器之后。该是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
[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)的更多相关文章
- [WebGL入门]十二,模型数据和顶点属性
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外.鄙人webgl研究还不够深入,一些专业词语.假设翻译有误.欢迎大家指 ...
- [WebGL入门]十四,绘制多边形
注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外,鄙人webgl研究还不够深入.一些专业词语,假设翻译有误,欢迎大家 ...
- WebGL入门教程(五)-webgl纹理
前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 WebGL入门教程(四)-webgl颜色 这里就需要用到 ...
- [WebGL入门]十六,绘制多个模型
注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入.一些专业词语.假设翻译有误.欢迎大家 ...
- [WebGL入门]十八,利用索引缓存来画图
注:文章译自http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:].另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...
- [WebGL入门]十九,遮挡剔除和深度測试
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误.欢迎大家指 ...
- [WebGL入门]十,矩阵计算和外部库
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...
- Android入门(十五)通知
原文链接:http://www.orlion.ga/663/ 1.通知的基本用法 创建通知的步骤,首先需要一个NotificationManager来对通知进行管理,可以调用Context的getSy ...
- Spring入门(十五):使用Spring JDBC操作数据库
在本系列的之前博客中,我们从没有讲解过操作数据库的方法,但是在实际的工作中,几乎所有的系统都离不开数据的持久化,所以掌握操作数据库的使用方法就非常重要. 在Spring中,操作数据库有很多种方法,我们 ...
随机推荐
- 洛谷 P1313 计算系数 (二项式定理)
这道题正好复习了二项式定理 所以答案就是a^n * b^m * c(n, k) 然后注意一些细节 我一开始写组合数只写一行的组合数 即c[0] = 1; c[i] = c[i-1] * (n - i ...
- 【【henuacm2016级暑期训练】动态规划专题 J】Red-Green Towers
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 显然最多1000行的样子. 从上到小做dp 设f[i][j]为前i行,使用了j个红色方块的方案数. f[1][r] = 1;如果r& ...
- Android 混淆后的代码调试
ProGuard的输出文件及用处 混淆之后,会给我们输出一些文件,在gradle方式下是在<project_dir>/build/proguard/目录下,ant是在<project ...
- POSIX 线程编程(一)简介
简介 在共享内存的多处理器结构中,可以用线程来实现并行.对于UNIX系统, IEEE POSIX 1003.1c标准规定了C语言线程编程接口的标准.这份标准的实现就是POSIX threads, 或者 ...
- [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 ...
- 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 ...
- Oracle RAC 实施
第 1 步 — 确定项目范围 理由 我们实施 Oracle RAC 是为了使我们的应用程序可伸缩和高度可用,以及为我们的客户提供更可靠的服务. 目标/可交付产品 该项目的最终产品将是一个新的 Orac ...
- Redis 安装与简单示例 <第一篇>【转】
一.Redis的安装 Redis下载地址如下:https://github.com/dmajkic/redis/downloads 解压后根据自己机器的实际情况选择32位或者64位.下载解压后图片如下 ...
- MySQL日期数据类型和时间类型使用总结
转自: http://blog.chinaunix.net/space.php?uid=11327712&do=blog&id=32416 MySQL 日期类型:日期格式.所占存储空间 ...
- SharePoint 使用Expression Web 设计网站
创建好网站以后可就可以开始发布了 possible causes : 1.The web server may not hava the FrontPage Server Extensions ins ...