Files
three.js/examples/geometry_terrain_gl.html
T
alteredq 255c042b1e Added clear color parameter to WebGLRenderer constructor, also added setClearColor API call.
This allows to work around ANGLE antialiasing issue appearing when compositing WebGL framebuffer with transparent background color with HTML canvas element background (while keeping antialiasing on).

WebGLRenderer constructor now takes JSON object with few optional parameters:

    renderer = new THREE.WebGLRenderer { scene: scene,
                                         antialias: true,
                                         clearColor: 0x000000,
                                         clearAlpha: 0 };

Here is how to change clear color in runtime:

    renderer.setClearColor( 0xff0000, 1 );
2010-12-25 22:32:26 +01:00

271 lines
6.7 KiB
HTML

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - geometry - webgl terrain</title>
<meta charset="utf-8">
<style type="text/css">
body {
color: #61443e;
font-family:Monospace;
font-size:13px;
text-align:center;
background-color: #bfd1e5;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: #a06851;
}
</style>
</head>
<body>
<div id="container"><br /><br /><br /><br /><br />Generating world...</div>
<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - webgl terrain demo<br />(left click: forward, right click: backward)</div>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript" src="js/ImprovedNoise.js"></script>
<script type="text/javascript" src="../build/Three.js"></script>
<script type="text/javascript" src="../src/extras/GeometryUtils.js"></script>
<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
<script type="text/javascript">
var container, stats;
var camera, scene, renderer;
var mesh, texture;
var worldWidth = 256, worldDepth = 256,
worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2;
var mouseX = 0, mouseY = 0,
lat = 0, lon = 0, phy = 0, theta = 0;
var direction = new THREE.Vector3(),
moveForward = false, moveBackward = false;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
setInterval( loop, 1000 / 60 );
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera( 60, window.innerWidth / window.innerHeight, 1, 20000 );
camera.target.position.z = - 100;
scene = new THREE.Scene();
data = generateHeight( worldWidth, worldDepth );
camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] + 500;
camera.target.position.y = camera.position.y;
var geometry = new Plane( 7500, 7500, worldWidth - 1, worldDepth - 1 );
for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
geometry.vertices[ i ].position.z = data[ i ] * 10;
}
texture = new THREE.Texture( generateTexture( data, worldWidth, worldDepth ), new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping );
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) );
mesh.rotation.x = - 90 * Math.PI / 180;
scene.addObject( mesh );
renderer = new THREE.WebGLRenderer( { scene: scene } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.innerHTML = "";
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
}
function generateHeight( width, height ) {
var size = width * height, data = new Float32Array( size ),
perlin = new ImprovedNoise(), quality = 1, z = Math.random() * 100;
for ( var i = 0; i < size; i ++ ) {
data[ i ] = 0
}
for ( var j = 0; j < 4; j ++ ) {
for ( var i = 0; i < size; i ++ ) {
var x = i % width, y = ~~ ( i / width );
data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 );
}
quality *= 5;
}
return data;
}
function generateTexture( data, width, height ) {
var canvas, canvasScaled, context, image, imageData,
level, diff, 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;
canvasScaled.loaded = true;
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;
}
function onDocumentMouseDown( event ) {
event.preventDefault();
event.stopPropagation();
switch ( event.button ) {
case 0: moveForward = true; break;
case 2: moveBackward = true; break;
}
}
function onDocumentMouseUp( event ) {
event.preventDefault();
event.stopPropagation();
switch ( event.button ) {
case 0: moveForward = false; break;
case 2: moveBackward = false; break;
}
}
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
function loop() {
if ( moveForward ) camera.translateZ( - 15 );
if ( moveBackward ) camera.translateZ( 15 );
lon += mouseX * 0.004;
lat -= mouseY * 0.004;
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = ( 90 - lat ) * Math.PI / 180;
theta = lon * Math.PI / 180;
camera.target.position.x = 100 * Math.sin( phi ) * Math.cos( theta ) + camera.position.x;
camera.target.position.y = 100 * Math.cos( phi ) + camera.position.y;
camera.target.position.z = 100 * Math.sin( phi ) * Math.sin( theta ) + camera.position.z;
renderer.render(scene, camera);
stats.update();
}
</script>
</body>
</html>