背景
本篇收录于《前端读书会》专栏
上文介绍了纹理相关的内容,并使用WebGL进行了2d的实现,今天延续上节课的内容对于纹理的3D实现 也算是吸取了MDN-Tutorial的模式,感觉这样的学习轨道 也算是初衷(每次长篇大论的讲图形学的理论我怕我和你都坚持不下去)目前来说最好的方式了,对于WebGL的学习还是图形学的学习都能有一个认识。话不多说开始今天的内容(大部分是code的讲解 尽可能快速过完一些基础的API...第一步成为一个API工程师)
上文介绍了纹理相关的内容,有需要可以参考上文
本篇大纲
- 2D与3D的区别?绘制思路?
- coding (WebGL中简单使用纹理)
coding部分引入webgl-utils(方面一些useprogram,linkProgram的简写 无太大魔力)&martix(矩阵的一些生成/计算..)工具类库
1.2d与3d的区别
首先我们都知道2D只是一个平面 3D可以理解为是6个平面,那么本篇文章最主要解决如何给添加5个平面就好(当然添加会伴随着一些问题,没关系 一步步的来)
本篇会对于上文的一些反馈进行改正 例如code 注释太少。。ok 我尽量多写点
WebGl coding 首先回顾一下步骤
- shader
- 创建program
- 处理坐标还有纹理相关
- 获取并绑定坐标信息
- 绘制draw
看着是如此简单 那么接下来我们一起来写一下
coding
coding开始之前先看看效果
缺一个gif图 明天找个有电脑的地方补充一下。
1. shader
有朋友反馈shader部分要照顾新手, 那么我逐行加下注释介绍下。当然更多细节信息还是得去看看相关资料呢。 我讲的不好(-- 主要是懒癌患者)
// vertex shader
// attribute变量 只能作用于顶点着色器 vec4 是矢量 a_position 一个变量名
attribute vec4 a_position;
// attribute变量 只能作用于顶点着色器 vec4 是矢量 a_position 一个变量名
attribute vec2 a_texcoord;
// uniform变量(全局) 可以在顶点和片元使用(如果俩个着色命名同名 可进行共享) mat4 是矩阵 u_matrix变量名
uniform mat4 u_matrix;
// varying变量(全局) 目的就是为了给片元传输数据 vec2 矢量 v_texcoord变量名
varying vec2 v_texcoord;
// main类似主执行函数 但是是必须的 C/C++用法类似
void main() {
// gl_Position 顶点坐标
gl_Position = u_matrix * a_position;
// 将纹理坐标传给片断着色器
v_texcoord = a_texcoord;
}
// fragment shader
// 精度限定 mediump中度精度 float数据类型 对了SL语言中是区分整型和浮点型的哦~
precision mediump float;
// varying变量(全局) 接收传输过来的数据 vec2 矢量 v_texcoord变量名
varying vec2 v_texcoord;
// uniform变量(只读 全局) sampler2D纹理 u_texture变量名
uniform sampler2D u_texture;
// 主执行函数
void main() {
// gl_FragColor 颜色信息 此处是纹理 texture2D是取样器纹理 v_texcoord纹理坐标 看js代码穿插理解
gl_FragColor = texture2D(u_texture, v_texcoord);
}
我这个注释写的 我都佩服。哈哈 不懂记得留言。我都让你们问,你们也不问。要知道不会就问没什么不好意思的 学会了那是自己的 强大自己升职加薪 加油
2. 创建program
// 用到了webgl-Utils 其实就是useVertex 和useFragment 然后linkProgram...
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
3. 处理坐标还有纹理相关
// 顶点坐标 发生了变换 6个面
var positions = new Float32Array(
[
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
]);
// 解决图片跨域问题 当然方式很多你也可以绘制canvas2d 然后创建纹理 canvas在标准上支持了图片跨域 有兴趣可以查查
function requestCORSIfNotSameOrigin(img, url) {
if ((new URL(url, window.location.href)).origin !== window.location.origin) {
img.crossOrigin = "";
}
}
// 加载图片 并在load完成绑定纹理
function loadImageAndCreateTextureInfo(url) {
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
var textureInfo = {
width: 1,
height: 1,
texture: tex,
};
var img = new Image();
img.addEventListener('load', function() {
textureInfo.width = img.width;
textureInfo.height = img.height;
gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture);
// 调用 texImage2D() 把已经加载的图片图形数据写到纹理
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
});
requestCORSIfNotSameOrigin(img, url);
img.src = url;
return textureInfo;
}
var texInfo = loadImageAndCreateTextureInfo('https://webglfundamentals.org/webgl/resources/leaves.jpg');
4. 获取并绑定坐标信息
var positionLocation = gl.getAttribLocation(program, "a_position");
var texcoordLocation = gl.getAttribLocation(program, "a_texcoord");
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
var textureLocation = gl.getUniformLocation(program, "u_texture");
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
setGeometry(gl);
var texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
setTexcoords(gl);
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]));
5. 使用program并提供buffer取数据 然后绘制
gl.vertexAttribPointer(
positionLocation, size, type, normalize, stride, offset);
// 启用texcoord属性
gl.enableVertexAttribArray(texcoordLocation);
// 绑定texcoord buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
....
gl.drawArrays(gl.TRIANGLES, 0, 6 * 6);
ok, 效果就这样实现了.为了大家的练习, 说明一下需要注意的地方是上面的代码 纹理是采用了一个纹理 如果要改多个图片可以采取多个纹理。也可以合并成一个纹理 通过坐标信息进行调节。
最后
最后强烈希望大家学习相关理论知识;理论可能日常用到的地方很少,但是它能决定你走多远。(有的人问难怎么办,勤于练习吧),写作速度呢 该专栏我加速(一周1-2篇) 其他专栏(1篇) 计算机图形学相关的基础知识都会带一遍。然后后续主要写数据可视化方向。
下一篇写点什么呢? 个人准备把MDN-Tutorial部分的内容结个尾。然后开始正式的可视化环节(可以介绍几个大家常用的库 2D 3D的都可以,大家看看有什么好用的库需要我一起过一下的呢)。或者大家提提意见!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。