ThreeJs入门38-拾取-创建2000个随机立方体

439 阅读2分钟

「这是我参与2022首次更文挑战的第42天,活动详情查看:2022首次更文挑战

示例代码采用three.js-r73版本: github.com/mrdoob/thre…

我们已经实战过渲染各种各样的场景,这一节,我们来创建一些随机的立方体,随机大小、颜色、位置显示在场景中,让我们来看看吧。

实现效果

  • 我们先来看下实现效果

GIF.gif

分析实现

  • 场景中的几何体颜色(其实是材质)、大小、位置是随机的,我们可以通过Math.random()来实现
  • 为了让物体更真实(有阴影面),我们采用Lambert网格材质,使用这种材质就要创建一个灯光,我们使用DirectionalLight平行光即可。
  • 场景中物体在运动,这个其实是摄像机在进行运动,物体相对看起来是在运动,所以我们需要创建一个按照一定规律进行运动的摄像机

初始化视图

  • 创建一个div容器,来放置我们的渲染器
function initView() {
    container = document.createElement("div");
    document.body.appendChild(container);
}

初始化场景

  • 创建一个场景,来放置我们的物体
function initScene() {
    scene = new THREE.Scene();
}

初始化灯光

  • 创建一个平行光
function initLight() {
    // 平行光
    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(1, 1, 1).normalize();
    scene.add(light);
}

灯光所在位置大概是这样的 image.png

初始化相机

  • 创建一个透视投影相机
const near = 1
const far = 10000

function initCamera() {
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, near, far);
}

初始化物体

  • 我们通过随机数,随机创建物体的材质、位置、大小
function initObject() {
    // 盒子
    var geometry = new THREE.BoxGeometry(20, 20, 20);
    
    // 创建2000个随机物体
    for (var i = 0; i < 2000; i++) {
      // 创建材质,材质颜色是随机的
      var material = new THREE.MeshLambertMaterial({
        color: Math.random() * 0xffffff,
      });

      var object = new THREE.Mesh(geometry, material);
      // 随机位置
      object.position.x = Math.random() * 800 - 400;
      object.position.y = Math.random() * 800 - 400;
      object.position.z = Math.random() * 800 - 400;
      // 随机旋转
      object.rotation.x = Math.random() * 2 * Math.PI;
      object.rotation.y = Math.random() * 2 * Math.PI;
      object.rotation.z = Math.random() * 2 * Math.PI;
      // 随机大小
      object.scale.x = Math.random() + 0.5;
      object.scale.y = Math.random() + 0.5;
      object.scale.z = Math.random() + 0.5;

      scene.add(object);
    }
}

初始化渲染器

function initRenderer() {
    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(0xf0f0f0);
    renderer.setPixelRatio(window.devicePixelRatio); // 设备像素比
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.sortObjects = false; // 是否排序
    container.appendChild(renderer.domElement);
}
  • renderer默认是对对象进行排序的,我们这个设置成false

渲染循环

  • 我们让摄像机围绕一个球进行旋转,让我们的场景动起来,这里我们是没有让物体运动的,是摄像机在运动。
function animate() {
  render();
  stats.update();
  requestAnimationFrame(animate);
}

function render() {
    theta += 0.1; // 旋转角度

    // 摄像机围绕一个球进行旋转
    camera.position.x = radius * Math.sin(THREE.Math.degToRad(theta));
    camera.position.y = radius * Math.sin(THREE.Math.degToRad(theta));
    camera.position.z = radius * Math.cos(THREE.Math.degToRad(theta));
    camera.lookAt(scene.position);
    // 更新相机矩阵
    camera.updateMatrixWorld();

    renderer.render(scene, camera);
}

codepen示例代码