Skip to content

网格

Grid

▶ 在线运行案例

网格

你将学到什么

  • WebGL 只画三角形 — Mesh 由三角面拼接
  • 手写 BufferGeometry + Float32Array 定义顶点
  • MeshBasicMaterialside: DoubleSide 双面渲染

效果说明

X-Z 平面上出现一个 蓝色三角形(实为两个三角形组成的矩形,本案例只定义一个三角面)。配合 OrbitControls 可旋转观察。

核心概念

GPU 渲染的基本图元是 三角形。一个矩形需要 2 个三角形 = 6 个顶点(无索引时)或 4 个顶点 + 索引。

顶点布局(Y=0 平面):

  (0,0,50) ---- (50,0,50)
     |    ╲       |
     |      ╲     |
  (0,0,0) ---- (50,0,0)

三角面1: (0,0,0) → (50,0,0) → (50,0,50)
三角面2: (0,0,0) → (0,0,50)  → (50,0,50)

本案例 只写 6 个顶点(2 个三角形) 构成完整矩形:

js
const vertices = new Float32Array([
    0, 0, 0,   50, 0, 0,   50, 0, 50,   // 三角面 1
    0, 0, 0,   0, 0, 50,   50, 0, 50,   // 三角面 2
]);
geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);
//                                                      itemSize=3 (x,y,z)

背面剔除: 默认只渲染正面(法线朝向相机的一侧)。side: THREE.DoubleSide 双面可见,适合平面/薄片。

实现步骤

  1. new THREE.BufferGeometry()
  2. Float32Array 填入 6 顶点 × 3 分量
  3. BufferAttribute(vertices, 3) 绑定到 attributes.position
  4. MeshBasicMaterial + DoubleSide → Mesh

代码要点

js
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
    0, 0, 0,  50, 0, 0,  50, 0, 50,
    0, 0, 0,  0, 0, 50,  50, 0, 50,
]);
geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);

const material = new THREE.MeshBasicMaterial({
    color: 0x0000ff,
    side: THREE.DoubleSide,  // 从背面也能看到
});

源码

js
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

const scene = new THREE.Scene();

// 网格模型 Mesh 其实就是一个一个三角形(面)拼接构成
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
    0, 0, 0,
    50, 0, 0,
    50, 0, 50,

    0, 0, 0,
    0, 0, 50,
    50, 0, 50,
]);

geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);

const material = new THREE.MeshBasicMaterial({
    color: 0x0000ff,
    side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

const camera = new THREE.PerspectiveCamera();
camera.position.set(200, 200, 200);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
const box = document.getElementById('box');
renderer.setSize(box.clientWidth, box.clientHeight);
box.appendChild(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', () => renderer.render(scene, camera));
renderer.render(scene, camera);

小结

入门案例 · Three.js · 6/15