4
头图

The final result is shown on the right (you can use the mouse, fingers or keyboard to control the rotation of the robot):

机器人预览

This project is based on image3D implementation.

Before the official start, we need to prepare the model data, you can download it here: model.json

If you want to quickly experience the ultimate effect, here view.

shader

First, you need to prepare two shaders.

vertex shader

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

fragment shader

<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

That is, a canvas:

<canvas width='500' height='500'></canvas>

drawing object

If it is not installed, you need to install the dependencies in advance:

npm install --save image3d

There are many methods on this drawing object. Through the methods on this object, various operations can be completed:

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
})

We need to use brushes and so on later, here, we get it in advance:

let painter = image3d.Painter() // 画笔
let buffer = image3d.Buffer() // 数据传递对象-缓冲区
let camera = image3d.Camera() // 相机

Set up the camera

The camera camera There are many ways you can specific here , call these methods cameras, etc. After adjusting the data to be passed to vertex shader:

image3d.setUniformMatrix("u_matrix", camera.value())

vertex data

After the camera is ready, it is the data, which is the vertex data in model.js

The model data format of different formats may be different. Take the data here as an example. The vertex data is included in: model.geometries[index].data.attributes.position.array . Therefore, we only need to model.geometries one by one. Let's take the first geometry as an example. (A model data may have one or more pieces of geometry stitched together):

let position=model.geometries[0].data.attributes.position.array

buffer.write(new Float32Array(position))
      .use('a_position', 3, 3, 0)

The function of the above is to position to the GPU and assign it to the variable a_position in the shader.

draw

At this point, a lot of points have been recorded in the GPU. These three points are connected to form a triangle, and the triangles are joined together to form a geometry. How to join these triangles? To use a brush:

 painter.drawTriangle(0, position.length / 3)

The final effect you can click here view.

concluding remarks

The complete code for this example is on Github: https://github.com/clunch-contrib/robot-3d .


你好2007
179 声望4 粉丝

走一步,再走一步。