|
@@ -1,356 +0,0 @@
|
|
|
-<!DOCTYPE html>
|
|
|
-<html lang="en">
|
|
|
- <head>
|
|
|
- <title>three.js webgl - geometry - minecraft - ao</title>
|
|
|
- <meta charset="utf-8">
|
|
|
- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
|
- <link type="text/css" rel="stylesheet" href="main.css">
|
|
|
- <style>
|
|
|
- body {
|
|
|
- background-color: #fff;
|
|
|
- color: #61443e;
|
|
|
- }
|
|
|
- a {
|
|
|
- color: #a06851;
|
|
|
- }
|
|
|
- </style>
|
|
|
- </head>
|
|
|
- <body>
|
|
|
-
|
|
|
- <div id="container"></div>
|
|
|
- <div id="info">
|
|
|
- <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - <a href="http://www.minecraft.net/" target="_blank" rel="noopener">minecraft</a> demo [ambient occlusion]. featuring <a href="http://painterlypack.net/" target="_blank" rel="noopener">painterly pack</a><br />(left click: forward, right click: backward)
|
|
|
- </div>
|
|
|
-
|
|
|
- <script type="module">
|
|
|
-
|
|
|
- import * as THREE from '../build/three.module.js';
|
|
|
-
|
|
|
- import Stats from './jsm/libs/stats.module.js';
|
|
|
-
|
|
|
- import { FirstPersonControls } from './jsm/controls/FirstPersonControls.js';
|
|
|
- import { ImprovedNoise } from './jsm/math/ImprovedNoise.js';
|
|
|
- import { BufferGeometryUtils } from './jsm/utils/BufferGeometryUtils.js';
|
|
|
-
|
|
|
- let container, stats;
|
|
|
-
|
|
|
- let camera, controls, scene, renderer;
|
|
|
-
|
|
|
- const worldWidth = 200, worldDepth = 200;
|
|
|
- const worldHalfWidth = worldWidth / 2;
|
|
|
- const worldHalfDepth = worldDepth / 2;
|
|
|
- const data = generateHeight( worldWidth, worldDepth );
|
|
|
-
|
|
|
- const clock = new THREE.Clock();
|
|
|
-
|
|
|
- init();
|
|
|
- animate();
|
|
|
-
|
|
|
- function init() {
|
|
|
-
|
|
|
- container = document.getElementById( 'container' );
|
|
|
-
|
|
|
- camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
|
|
|
- camera.position.y = getY( worldHalfWidth, worldHalfDepth ) * 100 + 100;
|
|
|
-
|
|
|
- scene = new THREE.Scene();
|
|
|
- scene.background = new THREE.Color( 0xffffff );
|
|
|
- scene.fog = new THREE.FogExp2( 0xffffff, 0.00015 );
|
|
|
-
|
|
|
- // sides
|
|
|
-
|
|
|
- const light = new THREE.Color( 0xffffff );
|
|
|
- const shadow = new THREE.Color( 0x505050 );
|
|
|
-
|
|
|
- const matrix = new THREE.Matrix4();
|
|
|
-
|
|
|
- const pxGeometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- pxGeometry.setAttribute( 'color', pxGeometry.attributes.position.clone() );
|
|
|
- pxGeometry.attributes.color.copyColorsArray( [ light, shadow, light, shadow, shadow, light ] );
|
|
|
- pxGeometry.attributes.uv.array[ 1 ] = 0.5;
|
|
|
- pxGeometry.attributes.uv.array[ 5 ] = 0.5;
|
|
|
- pxGeometry.attributes.uv.array[ 11 ] = 0.5;
|
|
|
- pxGeometry.rotateY( Math.PI / 2 );
|
|
|
- pxGeometry.translate( 50, 0, 0 );
|
|
|
-
|
|
|
- const nxGeometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- nxGeometry.setAttribute( 'color', nxGeometry.attributes.position.clone() );
|
|
|
- nxGeometry.attributes.color.copyColorsArray( [ light, shadow, light, shadow, shadow, light ] );
|
|
|
- nxGeometry.attributes.uv.array[ 1 ] = 0.5;
|
|
|
- nxGeometry.attributes.uv.array[ 5 ] = 0.5;
|
|
|
- nxGeometry.attributes.uv.array[ 11 ] = 0.5;
|
|
|
- nxGeometry.rotateY( - Math.PI / 2 );
|
|
|
- nxGeometry.translate( - 50, 0, 0 );
|
|
|
-
|
|
|
- const pyGeometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- pyGeometry.setAttribute( 'color', pyGeometry.attributes.position.clone() );
|
|
|
- pyGeometry.attributes.color.copyColorsArray( [ light, light, light, light, light, light ] );
|
|
|
- pyGeometry.attributes.uv.array[ 3 ] = 0.5;
|
|
|
- pyGeometry.attributes.uv.array[ 7 ] = 0.5;
|
|
|
- pyGeometry.attributes.uv.array[ 9 ] = 0.5;
|
|
|
- pyGeometry.rotateX( - Math.PI / 2 );
|
|
|
- pyGeometry.translate( 0, 50, 0 );
|
|
|
-
|
|
|
- const py2Geometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- py2Geometry.setAttribute( 'color', py2Geometry.attributes.position.clone() );
|
|
|
- py2Geometry.attributes.color.copyColorsArray( [ light, light, light, light, light, light ] );
|
|
|
- py2Geometry.attributes.uv.array[ 3 ] = 0.5;
|
|
|
- py2Geometry.attributes.uv.array[ 7 ] = 0.5;
|
|
|
- py2Geometry.attributes.uv.array[ 9 ] = 0.5;
|
|
|
- py2Geometry.rotateX( - Math.PI / 2 );
|
|
|
- py2Geometry.rotateY( Math.PI / 2 );
|
|
|
- py2Geometry.translate( 0, 50, 0 );
|
|
|
-
|
|
|
- const pzGeometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- pzGeometry.setAttribute( 'color', pzGeometry.attributes.position.clone() );
|
|
|
- pzGeometry.attributes.color.copyColorsArray( [ light, shadow, light, shadow, shadow, light ] );
|
|
|
- pzGeometry.attributes.uv.array[ 1 ] = 0.5;
|
|
|
- pzGeometry.attributes.uv.array[ 5 ] = 0.5;
|
|
|
- pzGeometry.attributes.uv.array[ 11 ] = 0.5;
|
|
|
- pzGeometry.translate( 0, 0, 50 );
|
|
|
-
|
|
|
- const nzGeometry = new THREE.PlaneGeometry( 100, 100 ).toNonIndexed();
|
|
|
- nzGeometry.setAttribute( 'color', nzGeometry.attributes.position.clone() );
|
|
|
- nzGeometry.attributes.color.copyColorsArray( [ light, shadow, light, shadow, shadow, light ] );
|
|
|
- nzGeometry.attributes.uv.array[ 1 ] = 0.5;
|
|
|
- nzGeometry.attributes.uv.array[ 5 ] = 0.5;
|
|
|
- nzGeometry.attributes.uv.array[ 11 ] = 0.5;
|
|
|
- nzGeometry.rotateY( Math.PI );
|
|
|
- nzGeometry.translate( 0, 0, - 50 );
|
|
|
-
|
|
|
- //
|
|
|
-
|
|
|
- const geometries = [];
|
|
|
-
|
|
|
- for ( let z = 0; z < worldDepth; z ++ ) {
|
|
|
-
|
|
|
- for ( let x = 0; x < worldWidth; x ++ ) {
|
|
|
-
|
|
|
- const h = getY( x, z );
|
|
|
-
|
|
|
- matrix.makeTranslation(
|
|
|
- x * 100 - worldHalfWidth * 100,
|
|
|
- h * 100,
|
|
|
- z * 100 - worldHalfDepth * 100
|
|
|
- );
|
|
|
-
|
|
|
- const px = getY( x + 1, z );
|
|
|
- const nx = getY( x - 1, z );
|
|
|
- const pz = getY( x, z + 1 );
|
|
|
- const nz = getY( x, z - 1 );
|
|
|
-
|
|
|
- const pxpz = getY( x + 1, z + 1 );
|
|
|
- const nxpz = getY( x - 1, z + 1 );
|
|
|
- const pxnz = getY( x + 1, z - 1 );
|
|
|
- const nxnz = getY( x - 1, z - 1 );
|
|
|
-
|
|
|
- const a = nx > h || nz > h || nxnz > h ? 0 : 1;
|
|
|
- const b = nx > h || pz > h || nxpz > h ? 0 : 1;
|
|
|
- const c = px > h || pz > h || pxpz > h ? 0 : 1;
|
|
|
- const d = px > h || nz > h || pxnz > h ? 0 : 1;
|
|
|
-
|
|
|
- if ( a + c > b + d ) {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = b === 0 ? shadow : light;
|
|
|
- colors[ 1 ] = c === 0 ? shadow : light;
|
|
|
- colors[ 2 ] = a === 0 ? shadow : light;
|
|
|
- colors[ 3 ] = c === 0 ? shadow : light;
|
|
|
- colors[ 4 ] = d === 0 ? shadow : light;
|
|
|
- colors[ 5 ] = a === 0 ? shadow : light;
|
|
|
-
|
|
|
- py2Geometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( py2Geometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = a === 0 ? shadow : light;
|
|
|
- colors[ 1 ] = b === 0 ? shadow : light;
|
|
|
- colors[ 2 ] = d === 0 ? shadow : light;
|
|
|
- colors[ 3 ] = b === 0 ? shadow : light;
|
|
|
- colors[ 4 ] = c === 0 ? shadow : light;
|
|
|
- colors[ 5 ] = d === 0 ? shadow : light;
|
|
|
-
|
|
|
- pyGeometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( pyGeometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ( px != h && px != h + 1 ) || x == 0 ) {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = pxpz > px && x > 0 ? shadow : light;
|
|
|
- colors[ 1 ] = shadow;
|
|
|
- colors[ 2 ] = pxnz > px && x > 0 ? shadow : light;
|
|
|
- colors[ 3 ] = shadow;
|
|
|
- colors[ 4 ] = shadow;
|
|
|
- colors[ 5 ] = pxnz > px && x > 0 ? shadow : light;
|
|
|
-
|
|
|
- pxGeometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( pxGeometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = nxnz > nx && x < worldWidth - 1 ? shadow : light;
|
|
|
- colors[ 1 ] = shadow;
|
|
|
- colors[ 2 ] = nxpz > nx && x < worldWidth - 1 ? shadow : light;
|
|
|
- colors[ 3 ] = shadow;
|
|
|
- colors[ 4 ] = shadow;
|
|
|
- colors[ 5 ] = nxpz > nx && x < worldWidth - 1 ? shadow : light;
|
|
|
-
|
|
|
- nxGeometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( nxGeometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = nxpz > pz && z < worldDepth - 1 ? shadow : light;
|
|
|
- colors[ 1 ] = shadow;
|
|
|
- colors[ 2 ] = pxpz > pz && z < worldDepth - 1 ? shadow : light;
|
|
|
- colors[ 3 ] = shadow;
|
|
|
- colors[ 4 ] = shadow;
|
|
|
- colors[ 5 ] = pxpz > pz && z < worldDepth - 1 ? shadow : light;
|
|
|
-
|
|
|
- pzGeometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( pzGeometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ( nz != h && nz != h + 1 ) || z == 0 ) {
|
|
|
-
|
|
|
- const colors = [];
|
|
|
-
|
|
|
- colors[ 0 ] = pxnz > nz && z > 0 ? shadow : light;
|
|
|
- colors[ 1 ] = shadow;
|
|
|
- colors[ 2 ] = nxnz > nz && z > 0 ? shadow : light;
|
|
|
- colors[ 3 ] = shadow;
|
|
|
- colors[ 4 ] = shadow;
|
|
|
- colors[ 5 ] = nxnz > nz && z > 0 ? shadow : light;
|
|
|
-
|
|
|
- nzGeometry.attributes.color.copyColorsArray( colors );
|
|
|
- geometries.push( nzGeometry.clone().applyMatrix4( matrix ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- const geometry = BufferGeometryUtils.mergeBufferGeometries( geometries );
|
|
|
- geometry.computeBoundingSphere();
|
|
|
-
|
|
|
- const texture = new THREE.TextureLoader().load( 'textures/minecraft/atlas.png' );
|
|
|
- texture.magFilter = THREE.NearestFilter;
|
|
|
-
|
|
|
- const mesh = new THREE.Mesh(
|
|
|
- geometry,
|
|
|
- new THREE.MeshLambertMaterial( { map: texture, vertexColors: true, side: THREE.DoubleSide } )
|
|
|
- );
|
|
|
- scene.add( mesh );
|
|
|
-
|
|
|
- const ambientLight = new THREE.AmbientLight( 0xcccccc );
|
|
|
- scene.add( ambientLight );
|
|
|
-
|
|
|
- const directionalLight = new THREE.DirectionalLight( 0xffffff, 2 );
|
|
|
- directionalLight.position.set( 1, 1, 0.5 ).normalize();
|
|
|
- scene.add( directionalLight );
|
|
|
-
|
|
|
- renderer = new THREE.WebGLRenderer();
|
|
|
- renderer.setPixelRatio( window.devicePixelRatio );
|
|
|
- renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
- container.appendChild( renderer.domElement );
|
|
|
-
|
|
|
- controls = new FirstPersonControls( camera, renderer.domElement );
|
|
|
-
|
|
|
- controls.movementSpeed = 1000;
|
|
|
- controls.lookSpeed = 0.125;
|
|
|
- controls.lookVertical = true;
|
|
|
- controls.constrainVertical = true;
|
|
|
- controls.verticalMin = 1.1;
|
|
|
- controls.verticalMax = 2.2;
|
|
|
-
|
|
|
- stats = new Stats();
|
|
|
- container.appendChild( stats.dom );
|
|
|
-
|
|
|
- //
|
|
|
-
|
|
|
- window.addEventListener( 'resize', onWindowResize );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function onWindowResize() {
|
|
|
-
|
|
|
- camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
- camera.updateProjectionMatrix();
|
|
|
-
|
|
|
- renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
-
|
|
|
- controls.handleResize();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function generateHeight( width, height ) {
|
|
|
-
|
|
|
- const data = [], perlin = new ImprovedNoise(),
|
|
|
- size = width * height, z = Math.random() * 100;
|
|
|
-
|
|
|
- let quality = 2;
|
|
|
-
|
|
|
- for ( let j = 0; j < 4; j ++ ) {
|
|
|
-
|
|
|
- if ( j == 0 ) for ( let i = 0; i < size; i ++ ) data[ i ] = 0;
|
|
|
-
|
|
|
- for ( let i = 0; i < size; i ++ ) {
|
|
|
-
|
|
|
- const x = i % width, y = ( i / width ) | 0;
|
|
|
- data[ i ] += perlin.noise( x / quality, y / quality, z ) * quality;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- quality *= 4;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return data;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function getY( x, z ) {
|
|
|
-
|
|
|
- return ( data[ x + z * worldWidth ] * 0.2 ) | 0;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
-
|
|
|
- function animate() {
|
|
|
-
|
|
|
- requestAnimationFrame( animate );
|
|
|
-
|
|
|
- render();
|
|
|
- stats.update();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function render() {
|
|
|
-
|
|
|
- controls.update( clock.getDelta() );
|
|
|
- renderer.render( scene, camera );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- </script>
|
|
|
-
|
|
|
- </body>
|
|
|
-</html>
|