乐趣区

关于webgl:如何基于模型数据绘制一个3D机器人

最终的成果如左边所示(你能够应用鼠标、手指或者键盘来管制这个机器人的旋转):

本我的项目基于 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>

绘图对象

这个绘图对象上有很多办法,通过这个对象上的办法,就能够实现各种操作了:

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…。

退出移动版