📜  如何在 webGL 和 p5.js 中创建 3D 几何?(1)

📅  最后修改于: 2023-12-03 15:38:28.282000             🧑  作者: Mango

在 webGL 和 p5.js 中创建 3D 几何

简介

在 3D 游戏或动画中,几何形状是非常重要的一部分。WebGL 和 p5.js 都提供了创建 3D 几何的库和功能。在本文中,我们将介绍如何在这两种库中创建 3D 几何。

webGL
创建基本几何

WebGL 可以利用顶点数组创建几何形状。下面是一些示例代码,以创建基本的几何体。

立方体

// 创建 8 个顶点
const vertices = [
  1, 1, 1,
  -1, 1, 1,
  -1, -1, 1,
  1, -1, 1,
  1, 1, -1,
  -1, 1, -1,
  -1, -1, -1,
  1, -1, -1
];

// 创建 12 个三角形
const indices = [
  0, 1, 2, 0, 2, 3,
  4, 5, 6, 4, 6, 7,
  0, 4, 7, 0, 7, 3,
  1, 5, 6, 1, 6, 2,
  0, 4, 5, 0, 5, 1,
  3, 2, 6, 3, 6, 7
];

// 创建缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

圆柱体

// 创建 360 个顶点
const vertices = [0, 0, 0];
let angle = 0;

for (let i = 0; i < 360; ++i) {
  vertices.push(Math.cos(angle), 0, Math.sin(angle));
  vertices.push(Math.cos(angle), 1, Math.sin(angle));
  angle += Math.PI / 180;
}

vertices.push(0, 0, 0);
vertices.push(0, 1, 0);

// 创建 720 个三角形
const indices = [];
for (let i = 1; i < 361; ++i) {
  indices.push(0, i, i + 1);
  indices.push(361 + i, 361 + i + 1, 722);
  indices.push(i, i + 1, 361 + i + 1);
  indices.push(361 + i + 1, 361 + i, i + 1);
}

// 创建缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

球体

// 创建 2452 个顶点(每 10 度一个顶点)
const vertices = [];
for (let i = 0; i < 18; ++i) {
  const latitude = (i / 18) * Math.PI;
  for (let j = 0; j < 36; ++j) {
    const longitude = (j / 36) * (Math.PI * 2);
    vertices.push(
      Math.sin(latitude) * Math.cos(longitude),
      Math.cos(latitude),
      Math.sin(latitude) * Math.sin(longitude)
    );
  }
}
vertices.push(0, 1, 0); // 顶部顶点
vertices.push(0, -1, 0); // 底部顶点

// 创建 4320 个三角形
const indices = [];
for (let i = 0; i < 17; ++i) {
  for (let j = 0; j < 36; ++j) {
    const topLeft = i * 36 + j;
    const topRight = i * 36 + (j + 1) % 36;
    const bottomLeft = (i + 1) * 36 + j;
    const bottomRight = (i + 1) * 36 + (j + 1) % 36;
    indices.push(topLeft, bottomLeft, topRight);
    indices.push(bottomRight, topRight, bottomLeft);
  }
}
for (let i = 0; i < 36; ++i) {
  indices.push(i, (i + 1) % 36, 1080);
  indices.push(1081, 1800 + i, 1800 + (i + 1) % 36);
}

// 创建缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
基本变换

在 WebGL 中,变换是通过修改顶点坐标来实现的。以下代码将对物体进行平移、旋转和缩放。

// 平移
const translationMatrix = [
  1, 0, 0, x,
  0, 1, 0, y,
  0, 0, 1, z,
  0, 0, 0, 1
];

// 旋转
const rotationXMatrix = [
  1, 0, 0, 0,
  0, cos(theta), -sin(theta), 0,
  0, sin(theta), cos(theta), 0,
  0, 0, 0, 1
];

const rotationYMatrix = [
  cos(theta), 0, sin(theta), 0,
  0, 1, 0, 0,
  -sin(theta), 0, cos(theta), 0,
  0, 0, 0, 1
];

const rotationZMatrix = [
  cos(theta), -sin(theta), 0, 0,
  sin(theta), cos(theta), 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1
];

// 缩放
const scaleMatrix = [
  x, 0, 0, 0,
  0, y, 0, 0,
  0, 0, z, 0,
  0, 0, 0, 1
];
着色器

WebGL 使用着色器来对几何体进行着色。以下代码是一个简单的着色器,用于使用颜色渲染几何体。

const VSHADER_SOURCE = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  uniform mat4 u_ModelMatrix;
  varying vec4 v_Color;

  void main() {
    gl_Position = u_ModelMatrix * a_Position;
    v_Color = a_Color;
  }
`;

const FSHADER_SOURCE = `
  precision mediump float;
  varying vec4 v_Color;

  void main() {
    gl_FragColor = v_Color;
  }
`;
p5.js
创建基本几何

在 p5.js 中,可以使用 p5.js 的内置函数来创建基本的几何体。以下是一些示例代码。

立方体

const size = 100;
const cube = createBox(size, size, size);

圆柱体

const radius = 50;
const height = 100;
const cylinder = createCylinder(radius, height);

球体

const radius = 50;
const sphere = createSphere(radius);
基本变换

在 p5.js 中,可以使用 p5.js 的内置函数来进行变换。以下是一些示例代码。

// 平移
translate(x, y, z);

// 旋转
rotateX(theta);
rotateY(theta);
rotateZ(theta);

// 缩放
scale(x, y, z);
着色器

在 p5.js 中,可以使用内置的着色器来对几何体进行着色。以下是一个简单的着色器示例。

const vert = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  uniform mat4 u_ModelMatrix;
  varying vec4 v_Color;

  void main() {
    gl_Position = u_ModelMatrix * a_Position;
    v_Color = a_Color;
  }
`;

const frag = `
  precision mediump float;
  varying vec4 v_Color;

  void main() {
    gl_FragColor = v_Color;
  }
`;

const shader = createShader(vert, frag);
结论

在本文中,我们介绍了如何在 WebGL 和 p5.js 中创建基本的 3D 几何体,并演示了如何进行基本的变换和着色。这只是 3D 游戏和动画编程的入门,但是掌握这些基础知识是非常重要的。