Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Voxel Terrain Generation with Three.js</title>
- <style>
- body {
- margin: 0;
- }
- canvas {
- display: block;
- }
- </style>
- </head>
- <body>
- <script type="module">
- import * as THREE from "./js/three.module.js";
- import { ImprovedNoise } from "./js/ImprovedNoise.js";
- import { FirstPersonControls } from "./js/FirstPersonControls.js";
- import { OrbitControls } from "./js/OrbitControls.js";
- const TERRAIN_SIZE = 200;
- const VOXEL_SIZE = 1;
- let scene = new THREE.Scene();
- let camera = new THREE.PerspectiveCamera(
- 75,
- window.innerWidth / window.innerHeight,
- 0.1,
- 1000
- );
- let renderer = new THREE.WebGLRenderer();
- renderer.setSize(window.innerWidth, window.innerHeight);
- document.body.appendChild(renderer.domElement);
- let light = new THREE.HemisphereLight(0xffffff, 0x666666, 1);
- scene.add(light);
- let directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
- directionalLight.position.set(
- (TERRAIN_SIZE * VOXEL_SIZE) / 2,
- 50,
- (TERRAIN_SIZE * VOXEL_SIZE) / 2
- );
- scene.add(directionalLight);
- function lerp(a, b, t) {
- return a + (b - a) * t;
- }
- function smoothstep(edge0, edge1, x) {
- let t = Math.min(Math.max((x - edge0) / (edge1 - edge0), 0), 1);
- return t * t * (3 - 2 * t);
- }
- function generateVoxelTerrain() {
- let noise = new ImprovedNoise();
- let noise2 = new ImprovedNoise();
- let terrain = new THREE.Group();
- let geometry = new THREE.BoxGeometry(
- VOXEL_SIZE,
- VOXEL_SIZE,
- VOXEL_SIZE
- );
- let materials = {
- plains: new THREE.MeshLambertMaterial({ color: 0x8dc63f }),
- desert: new THREE.MeshLambertMaterial({ color: 0xf0e68c }),
- forest: new THREE.MeshLambertMaterial({ color: 0x228b22 }),
- snowy: new THREE.MeshLambertMaterial({ color: 0xffffff }),
- };
- for (let x = 0; x < TERRAIN_SIZE; x++) {
- for (let z = 0; z < TERRAIN_SIZE; z++) {
- let biomeValue = noise2.noise(x / 50, 0, z / 50);
- let biome = getBiome(biomeValue);
- let height = getBiomeHeight(x, z, noise, biome);
- for (let y = 0; y < height; y++) {
- let voxel = new THREE.Mesh(geometry, materials[biome]);
- voxel.position.set(
- x * VOXEL_SIZE,
- y * VOXEL_SIZE,
- z * VOXEL_SIZE
- );
- terrain.add(voxel);
- }
- }
- }
- return terrain;
- }
- function getBiomeHeight(x, z, noise, biome) {
- let height = 0;
- if (biome === "plains") {
- height = Math.floor((noise.noise(x / 25, 0, z / 25) + 1) * 1.5) + 12;
- } else if (biome === "desert") {
- height = Math.floor((noise.noise(x / 10, 0, z / 10) + 1) * 4) + 10;
- } else if (biome === "forest") {
- height = Math.floor((noise.noise(x / 10, 0, z / 10) + 1) * 5) + 15;
- } else if (biome === "snowy") {
- height = Math.floor((noise.noise(x / 10, 0, z / 10) + 1) * 3) + 18;
- }
- return height;
- }
- function getBiome(value) {
- if (value < -0.5) {
- return "desert";
- } else if (value < 0) {
- return "plains";
- } else if (value < 0.5) {
- return "forest";
- } else {
- return "snowy";
- }
- }
- let terrain = generateVoxelTerrain();
- scene.add(terrain);
- camera.position.set(1, 1, 1);
- let controls = new OrbitControls(camera, renderer.domElement);
- controls.target.set(
- (TERRAIN_SIZE * VOXEL_SIZE) / 2,
- 0,
- (TERRAIN_SIZE * VOXEL_SIZE) / 2
- );
- controls.update();
- function animate() {
- requestAnimationFrame(animate);
- controls.update(1 / 60);
- renderer.render(scene, camera);
- }
- animate();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement