最终的效果如右边所示(你可以使用鼠标、手指或者键盘来控制这个机器人的旋转):
本项目基于image3D实现。
在正式开始之前,我们需要准备好模型数据,你可以去这里下载:model.json
如果想快速体验最终效果,可以点击此处查看。
着色器
首先,你需要准备好两个着色器。
顶点着色器
<script type='x-shader/x-vertex' id='vs'>
attribute vec3 a_position; // 顶点坐标
uniform mat4 u_matrix; // 变换矩阵
uniform vec3 u_LPosition; // 光的位置
attribute vec3 a_normal;
varying vec3 v_LDirection;
varying vec3 v_normal;
void main(){
// 坐标新增齐次坐标,为了和矩阵对齐
gl_Position=u_matrix * vec4(a_position,1);
// 点光源方向计算:点光源方向 = 点光源坐标 - 顶点坐标
// 顶点的位置应该使用计算过的
v_LDirection=u_LPosition-gl_Position.xyz;
v_normal=a_normal;
}
</script>
片段着色器
<script type='x-shader/x-fragment' id='fs'>
precision mediump float;
uniform vec4 u_LColor; // 光颜色
uniform vec4 u_color; // 顶点颜色
varying vec3 v_LDirection; // 光线方向
varying vec3 v_normal; // 法线方向
void main(){
// 先对方向进行序列化,使得向量长度为1
vec3 LDirection=normalize(v_LDirection);
vec3 normal=normalize(v_normal);
// 计算序列化后的光方向和法线方向的点乘
float dotValue=max(dot(LDirection,normal),0.2);
gl_FragColor=u_color*u_LColor*dotValue;
}
</script>
画布
也就是一个canvas:
<canvas width='500' height='500'></canvas>
绘图对象
如果没有安装,需要提前安装好依赖包:
npm install --save image3d
这个绘图对象上有很多方法,通过这个对象上的方法,就可以完成各种操作了:
import image3D from 'image3d'
// 创建3D对象并配置好画布和着色器
let image3d = new image3D(document.getElementsByTagName('canvas')[0], {
"vertex-shader": document.getElementById("vs").innerText,
"fragment-shader": document.getElementById("fs").innerText,
depth: true
})
我们后续需要使用到画笔等,在这里,我们提前获取好:
let painter = image3d.Painter() // 画笔
let buffer = image3d.Buffer() // 数据传递对象-缓冲区
let camera = image3d.Camera() // 相机
设置好相机
相机camera
上有很多的方法,具体的你可以点击此处,调用这些方法对相机等进行调整后,数据需要传递给顶点着色器
:
image3d.setUniformMatrix("u_matrix", camera.value())
顶点数据
相机准备好了以后,就是数据了,也就是model.js
中的顶点数据:
不同格式的模型数据格式可能不一样,拿我们这里的数据举例子,顶点的数据都包含在:model.geometries[index].data.attributes.position.array
中,因此,我们只需要把model.geometries
一个个绘制处理即可,我们以第一个几何体为例(一个模型数据可能有一个或多个几何体拼接而成):
let position=model.geometries[0].data.attributes.position.array
buffer.write(new Float32Array(position))
.use('a_position', 3, 3, 0)
上面的作用就是把数据position
写入GPU并分配给着色器中的变量a_position
。
绘制
此时,GPU中已经记录了好多的点,这些点3个连起来就是一个三角形,三角形拼接起来就是几何体了,如何把这些三角形拼接起来?使用画笔:
painter.drawTriangle(0, position.length / 3)
最终的效果你可以点击此处查看。
结束语
本例子的完整代码存放在Github上: https://github.com/clunch-con... 。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。