Three.js建筑森林

发布于:2025-02-10 ⋅ 阅读:(44) ⋅ 点赞:(0)

建筑森林-CSDN直播建筑森林https://live.csdn.net/v/460091https://live.csdn.net/v/460091

一.CSS部分

body {
  overflow:hidden;
  background:white;
}
canvas {
  display:block;
}

二.JS部分

const ANTIALIAS = true;
const CAMPOS = [0,-1,-10];
const FOV = 80;

//building height
const heightmap = `
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 f 0 0 f f a f d c 0 c f 0 0 
0 0 3 0 d 5 f 3 0 0 4 0 d 0 0 
0 1 0 8 4 0 0 0 6 0 0 0 f 0 0 
0 0 f 2 0 5 0 f 0 0 2 0 0 9 0 
0 a 0 0 0 0 0 0 0 f 0 0 1 f 0 
0 f 6 0 3 0 0 0 0 0 4 3 0 7 0 
7 f 0 d 1 0 0 0 0 0 0 1 2 6 0 
0 0 2 0 c 0 0 0 0 0 0 2 0 9 0 
0 f 0 c 0 0 0 0 0 0 2 5 f 0 0 
0 0 6 0 d 3 0 0 c 0 0 3 0 a 0 
7 0 0 c f 0 0 2 0 6 0 0 8 0 0 
0 0 d 0 0 f 1 0 0 0 c 0 f 0 0 
0 f 0 e d 0 c d 4 f 0 f 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
`.trim()
.split('\n')
.map(xs=>xs.split(' ').map(x=>parseInt(x,16)));
const SIDE = 10;
const ROWS = heightmap.length;
const COLS = heightmap[0].length;

let controls, camera, scene, renderer, light0;
init();
animate();

function init() {
  camera = new THREE.PerspectiveCamera(FOV,innerWidth/innerHeight,1,1000);
  camera.position.set(...CAMPOS);
  controls = new THREE.OrbitControls( camera );
  controls.minPolarAngle = Math.PI/180*150;
  controls.maxPolarAngle = Math.PI/180*180;
  controls.enableZoom = false;
  controls.update();
  
  // scene(fog)
  scene = new THREE.Scene();
  scene.fog = new THREE.Fog(0xffffff, 0.01, SIDE**2.5);

  // cubes
  for(let i = 0; i < ROWS; i++) {
    for(let j = 0; j < COLS; j++) {
      let height = heightmap[i][j]/0xf*SIDE**2.5;
      let metalness = height ? 0: Math.random();
      let roughness = height ? 1: Math.random();
      const steps = 0xff;
      const norm = heightmap[i][j]/0xf; 
      let color = grayscale(norm*steps|0);
      let emissive = color;
      let emissiveIntensity = 0.5;
      let mesh = genmesh({
        emissive,emissiveIntensity,color,
        height,metalness,roughness});
      let x = (j - ROWS/2)*SIDE;
      let z = (i - COLS/2)*SIDE;
      let y = height/2;
      mesh.position.set(x,y,z);
      scene.add(mesh);
    }
  }

  
  // lights
  light0 = new THREE.PointLight(0x104000, 0, 0, 2);
  light0.position.set(0, SIDE*10, 0);
  scene.add(light0);
  
  renderer = new THREE.WebGLRenderer({
    alpha:true,
    antialias:ANTIALIAS
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  //renderer.shadowMap.enabled = true;
  document.body.appendChild(renderer.domElement);
  //
  window.addEventListener("resize", onWindowResize, false);
}


function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}


function animate() {
  requestAnimationFrame(animate);
  scene.rotation.y += 0.0006;
  light0.intensity = Math.min(light0.intensity+0.01, 4);
  renderer.render(scene, camera);
  controls.update();
}


  function genmesh({
    emissiveIntensity, emissive,
    height=100,color=0xffffff,metalness=0,roughness=0.5}={}) {
    var geometry = new THREE.BoxBufferGeometry(SIDE,height,SIDE,3,10,3);
    var material = new THREE.MeshStandardMaterial({ 
      color, metalness, roughness, emissiveIntensity,
      emissive,
      wireframe:true
    });
    return mesh = new THREE.Mesh(geometry, material);
  }

function grayscale(i) {
  return (i << 16)+ (i << 8) + i;
}


网站公告

今日签到

点亮在社区的每一天
去签到