Template for use on discourse.threejs.org
This one uses the latest master branch
A Pen by Christopher M Overton on CodePen.
Template for use on discourse.threejs.org
This one uses the latest master branch
A Pen by Christopher M Overton on CodePen.
// Simple three.js example | |
var mesh, renderer, scene, camera, controls,texture; | |
var worldWidth = 400, worldDepth = 400, | |
worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2, tcount=0, objs=[]; | |
init(); | |
animate(); | |
var clock = new THREE.Clock(); | |
function init() { | |
// renderer | |
renderer = new THREE.WebGLRenderer(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
document.body.appendChild( renderer.domElement ); | |
// scene | |
scene = new THREE.Scene(); | |
// camera | |
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 ); | |
camera.position.set( 20, 20, 20 ); | |
// controls | |
controls = new THREE.OrbitControls( camera ); | |
scene.background = new THREE.Color( 0xbfd1e5 ); | |
// ambient light | |
scene.add( new THREE.AmbientLight( 0x222222 ) ); | |
// directional light | |
var light = new THREE.DirectionalLight( 0xffffff, 1 ); | |
light.position.set( 20, 20, 0 ); | |
scene.add( light ); | |
// axes | |
scene.add( new THREE.AxesHelper( 20 ) ); | |
/* | |
// geometry | |
var geometry = new THREE.SphereGeometry( 5, 12, 8 ); | |
// material | |
var material = new THREE.MeshPhongMaterial( { | |
color: 0x00ffff, | |
flatShading: true, | |
transparent: true, | |
opacity: 0.7, | |
} ); | |
// mesh | |
mesh = new THREE.Mesh( geometry, material ); | |
*/ | |
var data = generateHeight( worldWidth, worldDepth, 0, 0); | |
var data2 = generateHeight( worldWidth, worldDepth, 1, 0); | |
camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] * 10 + 3100; | |
var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); | |
var geometry2 = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); | |
geometry.rotateX( - Math.PI / 2 ); | |
geometry2.rotateX( - Math.PI / 2 ); | |
geometry2.translate(7500,0,0); | |
geometry.attributes.position.needsUpdate=true; | |
geometry2.attributes.position.needsUpdate=true; | |
var vertices = geometry.attributes.position.array; | |
var vertices2 = geometry2.attributes.position.array; | |
for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) { | |
vertices[ j + 1 ] = data[ i ] * 10; | |
vertices2[ j + 1 ] = data2[ i ] * 10; | |
} | |
texture = new THREE.CanvasTexture( generateTexture( data, worldWidth, worldDepth ) ); | |
texture.wrapS = THREE.ClampToEdgeWrapping; | |
texture.wrapT = THREE.ClampToEdgeWrapping; | |
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) ); | |
mesh.material.needsUpdate=true; | |
objs.push({mesh:mesh,trx:0,tileind:0}); | |
scene.add( mesh ); | |
texture2 = new THREE.CanvasTexture( generateTexture( data2, worldWidth, worldDepth ) ); | |
texture2.wrapS = THREE.ClampToEdgeWrapping; | |
texture2.wrapT = THREE.ClampToEdgeWrapping; | |
mesh2 = new THREE.Mesh( geometry2, new THREE.MeshBasicMaterial( { map: texture2 } ) ); | |
mesh2.material.needsUpdate=true; | |
objs.push({mesh:mesh2,trx:7500,tileind:1}); | |
scene.add( mesh2 ); | |
} | |
function animate() { | |
requestAnimationFrame( animate ); | |
renderer.render( scene, camera ); | |
if (tcount%2==0){ | |
let sp =-50; | |
let geom = objs[0].mesh.geometry.translate(sp,0,0); | |
objs[0].mesh.updateMatrix(); | |
let geom2 = objs[1].mesh.geometry.translate(sp,0,0); | |
objs[1].mesh.updateMatrix(); | |
objs[1].trx += sp; | |
if (objs[1].trx <= 0){ | |
updateTiles(); | |
} | |
// scene.remove(objs[0]); | |
} | |
tcount+=1; | |
} | |
function addNextTile(tileind){ | |
var data = generateHeight( worldWidth, worldDepth, tileind, 0); | |
let geometry = objs[1].mesh.geometry; | |
// var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); | |
// geometry.rotateX( - Math.PI / 2 ); | |
geometry.translate(2*7500,0,0); | |
objs[1].mesh.updateMatrix(); | |
var vertices = geometry.attributes.position.array; | |
var vertices = geometry.attributes.position.array; | |
for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) { | |
vertices[ j + 1 ] = data[ i ] * 10; | |
} | |
geometry.attributes.position.needsUpdate=true; | |
let texture = new THREE.CanvasTexture( generateTexture( data, worldWidth, worldDepth ) ); | |
texture.wrapS = THREE.ClampToEdgeWrapping; | |
texture.wrapT = THREE.ClampToEdgeWrapping; | |
objs[1].mesh.material.map=texture; | |
objs[1].mesh.material.map.needsUpdate = true; | |
//let mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) ); | |
objs[1].tileind=tileind; | |
objs[1].trx=7500; | |
// objs.push({mesh:mesh,trx:7500,tileind:tileind}); | |
//scene.add( mesh ); | |
} | |
function updateTiles(){ | |
// scene.remove(objs[0].mesh); | |
objs.push(objs[0]); | |
objs.shift(); | |
addNextTile(objs[0].tileind+1); | |
} | |
function lerp(t, a, b) { | |
return a + t * (b - a); | |
} | |
function clamp(v,min, max) { | |
return Math.min(Math.max(v, min), max); | |
}; | |
function generateHeight( width, height, trw, trh) { | |
var size = width * height, data = new Uint8Array( size ), data2 = new Uint8Array( size ), | |
perlin = new ImprovedNoise(), quality = .75, z = 0; | |
var b2 =1.0, q2 =.23453, q3 = 1.15, b3 = .56850, b4=.1,c1=1.50, c2=1.2; | |
for ( var j = 0; j < 6; j ++ ) { | |
for ( var i = 0; i < size; i ++ ) { | |
var x = (i % width)+trw*width, y = ~ ~ ( i / width ); y+=trh*height; | |
let t = clamp(perlin.noise(x/450,y/450,0)*c1,0,1); | |
let t2 = clamp(perlin.noise(x/550,y/550,0)*c2,0,1); | |
let h1 = Math.abs((perlin.noise( x / quality, y / quality, z )+1)* b2 *.15); | |
let h2 = Math.abs((perlin.noise( x / q2, y / q2, z )+1)* b3 *.0690123); | |
let h3 = lerp(t,h2,h1); | |
let h4 = Math.abs((perlin.noise( x / q3, y / q3, z )+1)* b4 *.347690123); | |
let h5 = lerp(t2,h3,h4); | |
data[ i ] += h5; | |
} | |
quality *= 2.5; | |
q2 *= 1.80975; | |
q3 *= 3.75 | |
b2 *= 3.5; | |
b3 *= 2.035; | |
b4 *= 5.0; | |
} | |
return data; | |
} | |
function generateTexture( data, width, height ) { | |
var canvas, canvasScaled, context, image, imageData, vector3, sun, shade; | |
vector3 = new THREE.Vector3( 0, 0, 0 ); | |
sun = new THREE.Vector3( 1, 1, 1 ); | |
sun.normalize(); | |
canvas = document.createElement( 'canvas' ); | |
canvas.width = width; | |
canvas.height = height; | |
context = canvas.getContext( '2d' ); | |
context.fillStyle = '#000'; | |
context.fillRect( 0, 0, width, height ); | |
image = context.getImageData( 0, 0, canvas.width, canvas.height ); | |
imageData = image.data; | |
for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++ ) { | |
vector3.x = data[ j - 2 ] - data[ j + 2 ]; | |
vector3.y = 2; | |
vector3.z = data[ j - width * 2 ] - data[ j + width * 2 ]; | |
vector3.normalize(); | |
shade = vector3.dot( sun ); | |
imageData[ i ] = ( 96 + shade * 128 ) * ( 0.5 + data[ j ] * 0.007 ); | |
imageData[ i + 1 ] = ( 32 + shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); | |
imageData[ i + 2 ] = ( shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); | |
} | |
context.putImageData( image, 0, 0 ); | |
// Scaled 4x | |
canvasScaled = document.createElement( 'canvas' ); | |
canvasScaled.width = width * 4; | |
canvasScaled.height = height * 4; | |
context = canvasScaled.getContext( '2d' ); | |
context.scale( 4, 4 ); | |
context.drawImage( canvas, 0, 0 ); | |
image = context.getImageData( 0, 0, canvasScaled.width, canvasScaled.height ); | |
imageData = image.data; | |
// /* | |
for ( var i = 0, l = imageData.length; i < l; i += 4 ) { | |
var v = ~ ~ ( Math.random() * 5 ); | |
imageData[ i ] += v; | |
imageData[ i + 1 ] += v; | |
imageData[ i + 2 ] += v; | |
} | |
//*/ | |
context.putImageData( image, 0, 0 ); | |
return canvasScaled; | |
} |
<script src="https://threejs.org/build/three.js"></script> | |
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> | |
<script src="https://threejs.org/examples/js/ImprovedNoise.js"></script> | |
<script src="https://threejs.org/examples/js/WebGL.js"></script> | |
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script> |
body { | |
background-color: #000; | |
margin: 0px; | |
overflow: hidden; | |
} |