Files
three.js/examples/webgl_materials_cubemap_dynamic.html
T
alteredq 81b60ea2f6 All WebGL examples working with array-less materials.
Noticeable difference: can't anymore assign Material references to faces directly - "face.materials" became "face.materialIndex". Materials have to go to "geometry.materials" array (to which "face.materialIndex" points). This is necessary to allow run-time changing of face materials (this indirection used to be done by arrays).

Some casualties:

- multi-materials example, this functionality isn't possible anymore
- had to simplify LOD Text examples as LODs don't handle groups (used to fake multi-materials)
- multi-materials sphere in materials example can't have faces with undefined materials (this may be fixable I guess, when there'll be some real use-case)
- scene format still has materials arrays, only the last material will be used (except when there are face materials, then materials from JSON will be used, as before)

Other renderers and their corresponding examples were not touched yet.

WebGLRenderer still needs some prettification, some things don't make sense anymore without arrays, code can be cleaned up further.
2011-10-21 06:18:59 +02:00

1016 lines
28 KiB
HTML

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js webgl - materials - dynamic cube reflection</title>
<meta charset="utf-8">
<style>
body {
background: #000;
color: #999;
padding: 0;
margin: 0;
overflow: hidden;
font-family: georgia;
font-size:1em;
text-align: center;
}
a { color: white }
#info { margin-top: 2em; }
#footer { width: 100%; margin: 2em auto; text-align: center; position: absolute; bottom: 0 }
#loading { color: orange; margin-top: 1em }
.h { color: skyblue }
.c { display: inline; margin-left: 1em }
</style>
</head>
<body>
<div id="info">
<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - webgl dynamic cube reflection demo -
veyron by <a href="http://artist-3d.com/free_3d_models/dnm/model_disp.php?uid=1129" target="_blank">Troyano</a> -
gallardo by <a href="http://artist-3d.com/free_3d_models/dnm/model_disp.php?uid=1711" target="_blank">machman_3d</a>
</div>
<div id="loading">Loading...</div>
<div id="container"></div>
<div id="footer">
cars control: <span class="h">WASD</span> / <span class="h">arrows</span>
<div class="c">cameras: <span class="h">1</span> / <span class="h">2</span> / <span class="h">3</span> / <span class="h">4</span>
/ <span class="h">5</span> / <span class="h">6</span>
</div>
<div class="c">
day / night: <span class="h">n</span>
</div>
<div class="c">
motion blur: <span class="h">b</span>
</div>
</div>
<script src="../build/Three.js"></script>
<script src="js/Detector.js"></script>
<script src="js/RequestAnimationFrame.js"></script>
<script src="js/Stats.js"></script>
<script src="js/ShaderExtras.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/BloomPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/SavePass.js"></script>
<script src="js/Car.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var FOLLOW_CAMERA = false;
var MARGIN = 100;
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
var SHADOW_MAP_WIDTH = 1024, SHADOW_MAP_HEIGHT = 1024;
var CUBE_HEIGHT = 0;
var container, stats;
var camera, cameraTarget, scene, renderer;
var renderTarget, renderTargetParameters;
var spotLight, ambientLight;
var cubeCamera;
var clock = new THREE.Clock();
var controlsGallardo = {
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false
};
var controlsVeyron = {
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false
};
var mlib;
var gallardo, veyron, currentCar;
var effectDirt, hblur, vblur, effectBloom, effectKeep, effectBlend, effectFXAA;
var config = {
"veyron" : { r: 0.5, model: null, backCam: new THREE.Vector3( 550, 100, -1000 ) },
"gallardo" : { r: 0.35, model: null, backCam: new THREE.Vector3( 550, 0, -1500 ) }
};
var flareA, flareB;
var sprites = [];
var ground, groundBasic;
var blur = false;
var v = 0.9, vdir = 1;
init();
animate();
function init() {
container = document.getElementById( 'container' );
// SCENE CAMERA
camera = new THREE.PerspectiveCamera( 18, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 );
camera.position.set( 2000, 0, 2000 );
cameraTarget = new THREE.Vector3( 0, 0, 0 );
// SCENE
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xffffff, 3000, 10000 );
scene.fog.color.setHSV( 0.51, 0.5, 0.9 );
createScene();
// LIGHTS
ambientLight = new THREE.AmbientLight( 0x555555 );
scene.add( ambientLight );
spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 0, 1800, 1500 );
spotLight.target.position.set( 0, 0, 0 );
spotLight.castShadow = true;
scene.add( spotLight );
directionalLight2 = new THREE.PointLight( 0xff9900, 0.25 );
directionalLight2.position.set( 0.5, -1, 0.5 );
//directionalLight2.position.normalize();
//scene.add( directionalLight2 );
// RENDERER
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.setClearColor( scene.fog.color, 1 );
renderer.domElement.style.position = "absolute";
renderer.domElement.style.top = MARGIN + "px";
renderer.domElement.style.left = "0px";
container.appendChild( renderer.domElement );
// SHADOW
renderer.shadowCameraNear = 2;
renderer.shadowCameraFar = camera.far;
renderer.shadowCameraFov = 50;
renderer.shadowMapBias = 0.003885;
renderer.shadowMapDarkness = 0.5;
renderer.shadowMapWidth = SHADOW_MAP_WIDTH;
renderer.shadowMapHeight = SHADOW_MAP_HEIGHT;
renderer.shadowMapEnabled = true;
//renderer.shadowMapSoft = false;
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
stats.domElement.children[ 0 ].children[ 0 ].style.color = "#888";
stats.domElement.children[ 0 ].style.background = "#000";
stats.domElement.children[ 0 ].children[ 1 ].style.display = "none";
// CUBE CAMERA
cubeCamera = new THREE.CubeCamera( 1, 100000, CUBE_HEIGHT, 128 );
// MATERIALS
var cubeTarget = cubeCamera.renderTarget;
mlib = {
body: [],
"Chrome": new THREE.MeshLambertMaterial( { color: 0xffffff, ambient: 0xffffff, envMap: cubeTarget } ),
"ChromeN": new THREE.MeshLambertMaterial( { color: 0xffffff, ambient: 0xffffff, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.75 } ),
"Dark chrome": new THREE.MeshLambertMaterial( { color: 0x444444, ambient: 0x444444, envMap: cubeTarget } ),
"Black rough": new THREE.MeshLambertMaterial( { color: 0x050505, ambient: 0x050505 } ),
"Dark glass": new THREE.MeshLambertMaterial( { color: 0x101020, ambient: 0x101020, envMap: cubeTarget, opacity: 0.5, transparent: true } ),
"Orange glass": new THREE.MeshLambertMaterial( { color: 0xffbb00, ambient: 0xffbb00, opacity: 0.5, transparent: true } ),
"Red glass": new THREE.MeshLambertMaterial( { color: 0xff0000, ambient: 0xff0000, opacity: 0.5, transparent: true } ),
"Black metal": new THREE.MeshLambertMaterial( { color: 0x222222, ambient: 0x222222, envMap: cubeTarget, combine: THREE.MultiplyOperation } ),
"Orange metal": new THREE.MeshLambertMaterial( { color: 0xff6600, ambient: 0xff6600, envMap: cubeTarget, combine: THREE.MultiplyOperation } )
}
mlib.body.push( [ "Orange", new THREE.MeshLambertMaterial( { color: 0x883300, ambient: 0x883300, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.1 } ) ] );
mlib.body.push( [ "Blue", new THREE.MeshLambertMaterial( { color: 0x113355, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.1 } ) ] );
mlib.body.push( [ "Red", new THREE.MeshLambertMaterial( { color: 0x660000, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.1 } ) ] );
mlib.body.push( [ "Black", new THREE.MeshLambertMaterial( { color: 0x000000, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.2 } ) ] );
mlib.body.push( [ "White", new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.2 } ) ] );
mlib.body.push( [ "Carmine", new THREE.MeshPhongMaterial( { color: 0x770000, specular: 0xffaaaa, envMap: cubeTarget, combine: THREE.MultiplyOperation } ) ] );
mlib.body.push( [ "Gold", new THREE.MeshPhongMaterial( { color: 0xaa9944, specular: 0xbbaa99, shininess: 50, envMap: cubeTarget, combine: THREE.MultiplyOperation } ) ] );
mlib.body.push( [ "Bronze", new THREE.MeshPhongMaterial( { color: 0x150505, specular: 0xee6600, shininess: 10, envMap: cubeTarget, combine: THREE.MixOperation, reflectivity: 0.2 } ) ] );
mlib.body.push( [ "Chrome", new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0xffffff, envMap: cubeTarget, combine: THREE.MultiplyOperation } ) ] );
// FLARES
flareA = THREE.ImageUtils.loadTexture( "textures/lensflare2.jpg" );
flareB = THREE.ImageUtils.loadTexture( "textures/lensflare0.png" );
// CARS - VEYRON
veyron = new THREE.Car();
veyron.modelScale = 3;
veyron.backWheelOffset = 2;
veyron.callback = function( object ) {
addCar( object, -300, -215, 0, 0 );
setMaterialsVeyron( object );
var sa = 2, sb = 5;
var params = {
"a" : { map: flareA, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
"b" : { map: flareB, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
"ar" : { map: flareA, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending },
"br" : { map: flareB, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending }
};
var flares = [ // front
[ "a", sa, [ 47, 38, 120 ] ], [ "a", sa, [ 40, 38, 120 ] ], [ "a", sa, [ 32, 38, 122 ] ],
[ "b", sb, [ 47, 38, 120 ] ], [ "b", sb, [ 40, 38, 120 ] ], [ "b", sb, [ 32, 38, 122 ] ],
[ "a", sa, [ -47, 38, 120 ] ], [ "a", sa, [ -40, 38, 120 ] ], [ "a", sa, [ -32, 38, 122 ] ],
[ "b", sb, [ -47, 38, 120 ] ], [ "b", sb, [ -40, 38, 120 ] ], [ "b", sb, [ -32, 38, 122 ] ],
// back
[ "ar", sa, [ 22, 50, -123 ] ], [ "ar", sa, [ 32, 49, -123 ] ],
[ "br", sb, [ 22, 50, -123 ] ], [ "br", sb, [ 32, 49, -123 ] ],
[ "ar", sa, [ -22, 50, -123 ] ], [ "ar", sa, [ -32, 49, -123 ] ],
[ "br", sb, [ -22, 50, -123 ] ], [ "br", sb, [ -32, 49, -123 ] ],
];
for ( var i = 0; i < flares.length; i ++ ) {
var p = params[ flares[ i ][ 0 ] ];
var s = flares[ i ][ 1 ];
var x = flares[ i ][ 2 ][ 0 ];
var y = flares[ i ][ 2 ][ 1 ];
var z = flares[ i ][ 2 ][ 2 ];
var sprite = new THREE.Sprite( p );
sprite.scale.set( s, s, s );
sprite.position.set( x, y, z );
object.bodyMesh.add( sprite );
sprites.push( sprite );
}
checkStatus();
};
veyron.loadPartsBinary( "obj/veyron/parts/veyron_body_bin.js", "obj/veyron/parts/veyron_wheel_bin.js" );
// CARS - GALLARDO
gallardo = new THREE.Car();
gallardo.modelScale = 2;
gallardo.backWheelOffset = 45;
gallardo.callback = function( object ) {
addCar( object, 300, -110, 0, -110 );
setMaterialsGallardo( object );
var sa = 2, sb = 5;
var params = {
"a" : { map: flareA, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
"b" : { map: flareB, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
"ar" : { map: flareA, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending },
"br" : { map: flareB, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending }
};
var flares = [ // front
[ "a", sa, [ 70, 10, 160 ] ], [ "a", sa, [ 66, -1, 175 ] ], [ "a", sa, [ 66, -1, 165 ] ],
[ "b", sb, [ 70, 10, 160 ] ], [ "b", sb, [ 66, -1, 175 ] ], [ "b", sb, [ 66, -1, 165 ] ],
[ "a", sa, [ -70, 10, 160 ] ], [ "a", sa, [ -66, -1, 175 ] ], [ "a", sa, [ -66, -1, 165 ] ],
[ "b", sb, [ -70, 10, 160 ] ], [ "b", sb, [ -66, -1, 175 ] ], [ "b", sb, [ -66, -1, 165 ] ],
// back
[ "ar", sa, [ 61, 19, -185 ] ], [ "ar", sa, [ 55, 19, -185 ] ],
[ "br", sb, [ 61, 19, -185 ] ], [ "br", sb, [ 55, 19, -185 ] ],
[ "ar", sa, [ -61, 19, -185 ] ], [ "ar", sa, [ -55, 19, -185 ] ],
[ "br", sb, [ -61, 19, -185 ] ], [ "br", sb, [ -55, 19, -185 ] ],
];
for ( var i = 0; i < flares.length; i ++ ) {
var p = params[ flares[ i ][ 0 ] ];
var s = flares[ i ][ 1 ];
var x = flares[ i ][ 2 ][ 0 ];
var y = flares[ i ][ 2 ][ 1 ];
var z = flares[ i ][ 2 ][ 2 ];
var sprite = new THREE.Sprite( p );
sprite.scale.set( s, s, s );
sprite.position.set( x, y, z );
object.bodyMesh.add( sprite );
sprites.push( sprite );
}
checkStatus();
};
gallardo.loadPartsBinary( "obj/gallardo/parts/gallardo_body_bin.js", "obj/gallardo/parts/gallardo_wheel_bin.js" );
//
config[ "gallardo" ].model = gallardo;
config[ "veyron" ].model = veyron;
currentCar = gallardo;
// EVENTS
document.addEventListener( 'keydown', onKeyDown, false );
document.addEventListener( 'keyup', onKeyUp, false );
window.addEventListener( 'resize', onWindowResize, false );
// POSTPROCESSING
renderer.autoClear = false;
renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBufer: false };
renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
effectSave = new THREE.SavePass( new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters ) );
effectBlend = new THREE.ShaderPass( THREE.ShaderExtras[ "blend" ], "tDiffuse1" );
effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] );
var effectVignette = new THREE.ShaderPass( THREE.ShaderExtras[ "vignette" ] );
var effectBleach = new THREE.ShaderPass( THREE.ShaderExtras[ "bleachbypass" ] );
effectBloom = new THREE.BloomPass( 0.75 );
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCREEN_WIDTH, 1 / SCREEN_HEIGHT );
// tilt shift
hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalTiltShift" ] );
vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalTiltShift" ] );
var bluriness = 7;
hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH;
vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT;
if ( FOLLOW_CAMERA ) {
if ( currentCar == gallardo ) {
hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = rMap[ "gallardo" ];
} else if ( currentCar == veyron ) {
hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = rMap[ "veyron" ];
}
} else {
hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = 0.35;
}
effectVignette.uniforms[ "offset" ].value = 1.05;
effectVignette.uniforms[ "darkness" ].value = 1.5;
// motion blur
effectBlend.uniforms[ 'tDiffuse2' ].texture = effectSave.renderTarget;
effectBlend.uniforms[ 'mixRatio' ].value = 0.65;
var renderModel = new THREE.RenderPass( scene, camera );
effectVignette.renderToScreen = true;
composer = new THREE.EffectComposer( renderer, renderTarget );
composer.addPass( renderModel );
composer.addPass( effectFXAA );
composer.addPass( effectBlend );
composer.addPass( effectSave );
composer.addPass( effectBloom );
composer.addPass( effectBleach );
composer.addPass( hblur );
composer.addPass( vblur );
composer.addPass( effectVignette );
}
//
function checkStatus() {
if ( gallardo.loaded && veyron.loaded ) {
document.getElementById( "loading" ).style.display = "none";
}
}
//
function setSpritesOpacity( opacity ) {
for ( var i = 0; i < sprites.length; i ++ ) {
sprites[ i ].opacity = opacity;
}
}
//
function createScene() {
// GROUND
var texture = THREE.ImageUtils.loadTexture( "textures/cube/Park3Med/ny.jpg" );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 50, 50 );
groundBasic = new THREE.MeshBasicMaterial( { color: 0xffffff, map: texture } );
groundBasic.color.setHSV( 0.1, 0.45, 0.995 );
ground = new THREE.Mesh( new THREE.PlaneGeometry( 50000, 50000 ), groundBasic );
ground.rotation.x = - Math.PI / 2;
ground.position.y = - 215;
scene.add( ground );
ground.castShadow = false;
ground.receiveShadow = true;
// OBJECTS
var cylinderGeometry = new THREE.CylinderGeometry( 2, 50, 1000, 32 );
var sphereGeometry = new THREE.SphereGeometry( 100, 32, 16 );
var sy1 = -500 + 38;
var sy2 = -88;
addObject( cylinderGeometry, 0xff0000, 1500, 250, 0, sy1 );
addObject( cylinderGeometry, 0xffaa00, -1500, 250, 0, sy1 );
addObject( cylinderGeometry, 0x00ff00, 0, 250, 1500, sy1 );
addObject( cylinderGeometry, 0x00ffaa, 0, 250, -1500, sy1 );
addObject( sphereGeometry, 0xff0000, 1500, -125, 200, sy2 );
addObject( sphereGeometry, 0xffaa00, -1500, -125, 200, sy2 );
addObject( sphereGeometry, 0x00ff00, 200, -125, 1500, sy2 );
addObject( sphereGeometry, 0x00ffaa, 200, -125, -1500, sy2 );
}
//
function addObject( geometry, color, x, y, z, sy ) {
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: color, ambient: color } ) );
object.position.set( x, y, z );
scene.add( object );
object.castShadow = true;
object.receiveShadow = true;
var shadowTexture = THREE.ImageUtils.loadTexture( "textures/shadowAlpha.png" );
var shadowPlane = new THREE.PlaneGeometry( 400, 400 );
var shadowMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: 0.35, transparent: true,
map: shadowTexture,
polygonOffset: false, polygonOffsetFactor: -0.5, polygonOffsetUnits: 1 } );
var shadow = new THREE.Mesh( shadowPlane, shadowMaterial );
shadow.rotation.x = -Math.PI/2;
shadow.rotation.z = Math.PI/2;
shadow.position.y = sy;
object.add( shadow );
}
//
function generateDropShadowTexture( object, width, height, bluriness ) {
var renderTargetParameters = { minFilter: THREE.LinearMipmapLinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBufer: false };
var shadowTarget = new THREE.WebGLRenderTarget( width, height, renderTargetParameters );
var shadowMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
var shadowGeometry = THREE.GeometryUtils.clone( object.geometry );
var shadowObject = new THREE.Mesh( shadowGeometry, shadowMaterial );
var shadowScene = new THREE.Scene();
shadowScene.add( shadowObject );
shadowObject.geometry.computeBoundingBox();
var bb = shadowObject.geometry.boundingBox;
var margin = 0.15,
width = bb.z[ 1 ] - bb.z[ 0 ],
height = bb.x[ 1 ] - bb.x[ 0 ],
depth = bb.y[ 1 ] - bb.y[ 0 ],
left = bb.z[ 0 ] - margin * width,
right = bb.z[ 1 ] + margin * width,
top = bb.x[ 1 ] + margin * height,
bottom = bb.x[ 0 ] - margin * height,
near = bb.y[ 1 ] + margin * depth,
far = bb.y[ 0 ] - margin * depth;
var topCamera = new THREE.OrthographicCamera( left, right, top, bottom, near, far );
topCamera.position.y = bb.y[ 1 ];
topCamera.lookAt( shadowScene.position );
var renderShadow = new THREE.RenderPass( shadowScene, topCamera );
var blurShader = THREE.ShaderExtras[ "triangleBlur" ];
var effectBlurX = new THREE.ShaderPass( blurShader, 'texture' );
var effectBlurY = new THREE.ShaderPass( blurShader, 'texture' );
renderShadow.clearColor = new THREE.Color( 0x000000 );
renderShadow.clearAlpha = 0;
var blurAmountX = bluriness / width;
var blurAmountY = bluriness / height;
effectBlurX.uniforms[ 'delta' ].value = new THREE.Vector2( blurAmountX, 0 );
effectBlurY.uniforms[ 'delta' ].value = new THREE.Vector2( 0, blurAmountY );
var shadowComposer = new THREE.EffectComposer( renderer, shadowTarget );
shadowComposer.addPass( renderShadow );
shadowComposer.addPass( effectBlurX );
shadowComposer.addPass( effectBlurY );
renderer.clear();
shadowComposer.render( 0.1 );
return shadowTarget;
}
//
function addCar( object, x, y, z, s ) {
object.root.position.set( x, y, z );
scene.add( object.root );
object.enableShadows( true );
if ( FOLLOW_CAMERA && object == currentCar ) {
object.root.add( camera );
camera.position.set( 350, 500, 2200 );
//camera.position.set( 0, 3000, -500 );
cameraTarget.z = 500;
cameraTarget.y = 150;
camera.lookAt( cameraTarget );
}
var shadowTexture = generateDropShadowTexture( object.bodyMesh, 64, 32, 15 );
object.bodyMesh.geometry.computeBoundingBox();
var bb = object.bodyMesh.geometry.boundingBox;
var ss = object.modelScale * 1.0;
var shadowWidth = ss * ( bb.z[ 1 ] - bb.z[ 0 ] );
var shadowHeight = 1.25 * ss * ( bb.x[ 1 ] - bb.x[ 0 ] );
var shadowPlane = new THREE.PlaneGeometry( shadowWidth, shadowHeight );
var shadowMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, opacity: 0.5, transparent: true,
map: shadowTexture,
polygonOffset: false, polygonOffsetFactor: -0.5, polygonOffsetUnits: 1 } );
var shadow = new THREE.Mesh( shadowPlane, shadowMaterial );
shadow.rotation.x = -Math.PI/2;
shadow.rotation.z = Math.PI/2;
shadow.position.y = s + 10;
object.root.add( shadow );
}
//
function setCurrentCar( car, cameraType ) {
var oldCar = currentCar;
currentCar = config[ car ].model;
if ( cameraType == "front" || cameraType == "back" ) {
hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = config[ car ].r;
FOLLOW_CAMERA = true;
oldCar.root.remove( camera );
currentCar.root.add( camera );
if ( cameraType == "front" ) {
camera.position.set( 350, 500, 2200 );
} else if ( cameraType == "back" ) {
camera.position.copy( config[ car ].backCam );
}
cameraTarget.set( 0, 150, 500 );
} else {
FOLLOW_CAMERA = false;
oldCar.root.remove( camera );
camera.position.set( 2000, 0, 2000 );
cameraTarget.set( 0, 0, 0 );
spotLight.position.set( 0, 1800, 1500 );
hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = 0.35;
}
}
//
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
composer.reset( renderTarget );
hblur.uniforms[ 'h' ].value = 10.75 / SCREEN_WIDTH;
vblur.uniforms[ 'v' ].value = 10.75 / SCREEN_HEIGHT;
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCREEN_WIDTH, 1 / SCREEN_HEIGHT );
}
//
function onKeyDown ( event ) {
switch( event.keyCode ) {
case 38: /*up*/ controlsGallardo.moveForward = true; break;
case 87: /*W*/ controlsVeyron.moveForward = true; break;
case 40: /*down*/controlsGallardo.moveBackward = true; break;
case 83: /*S*/ controlsVeyron.moveBackward = true; break;
case 37: /*left*/controlsGallardo.moveLeft = true; break;
case 65: /*A*/ controlsVeyron.moveLeft = true; break;
case 39: /*right*/controlsGallardo.moveRight = true; break;
case 68: /*D*/ controlsVeyron.moveRight = true; break;
case 49: /*1*/ setCurrentCar( "gallardo", "center" ); break;
case 50: /*2*/ setCurrentCar( "veyron", "center" ); break;
case 51: /*3*/ setCurrentCar( "gallardo", "front" ); break;
case 52: /*4*/ setCurrentCar( "veyron", "front" ); break;
case 53: /*5*/ setCurrentCar( "gallardo", "back" ); break;
case 54: /*6*/ setCurrentCar( "veyron", "back" ); break;
case 78: /*N*/ vdir *= -1; break;
case 66: /*B*/ blur = !blur; break;
}
};
function onKeyUp ( event ) {
switch( event.keyCode ) {
case 38: /*up*/controlsGallardo.moveForward = false; break;
case 87: /*W*/ controlsVeyron.moveForward = false; break;
case 40: /*down*/controlsGallardo.moveBackward = false; break;
case 83: /*S*/ controlsVeyron.moveBackward = false; break;
case 37: /*left*/controlsGallardo.moveLeft = false; break;
case 65: /*A*/ controlsVeyron.moveLeft = false; break;
case 39: /*right*/controlsGallardo.moveRight = false; break;
case 68: /*D*/ controlsVeyron.moveRight = false; break;
}
};
//
function setMaterialsGallardo( car ) {
// BODY
var materials = car.bodyGeometry.materials;
materials[ 0 ] = mlib.body[ 0 ][ 1 ]; // body
materials[ 1 ] = mlib[ "Dark chrome" ]; // front under lights, back
// WHEELS
materials = car.wheelGeometry.materials;
materials[ 0 ] = mlib[ "Chrome" ]; // insides
materials[ 1 ] = mlib[ "Black rough" ]; // tire
}
function setMaterialsVeyron( car ) {
// 0 - top, front center, back sides
// 1 - front sides
// 2 - engine
// 3 - small chrome things
// 4 - backlights
// 5 - back signals
// 6 - bottom, interior
// 7 - windshield
// BODY
var materials = car.bodyGeometry.materials;
materials[ 0 ] = mlib[ "Black metal" ]; // top, front center, back sides
materials[ 1 ] = mlib[ "Chrome" ]; // front sides
materials[ 2 ] = mlib[ "Chrome" ]; // engine
materials[ 3 ] = mlib[ "Dark chrome" ]; // small chrome things
materials[ 4 ] = mlib[ "Red glass" ]; // backlights
materials[ 5 ] = mlib[ "Orange glass" ]; // back signals
materials[ 6 ] = mlib[ "Black rough" ]; // bottom, interior
materials[ 7 ] = mlib[ "Dark glass" ]; // windshield
// WHEELS
materials = car.wheelGeometry.materials;
materials[ 0 ] = mlib[ "Chrome" ]; // insides
materials[ 1 ] = mlib[ "Black rough" ]; // tire
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
var delta = clock.getDelta();
// day / night
v = THREE.Math.clamp( v + 0.5 * delta * vdir, 0.1, 0.9 );
scene.fog.color.setHSV( 0.51, 0.5, v );
renderer.setClearColor( scene.fog.color, 1 );
var vnorm = ( v - 0.05 ) / ( 0.9 - 0.05 );
if ( vnorm < 0.3 ) {
setSpritesOpacity( 1 - v / 0.3 );
} else {
setSpritesOpacity( 0 );
}
if ( vnorm < 0.4 ) {
if ( veyron.loaded ) {
veyron.bodyGeometry.materials[ 1 ] = mlib[ "ChromeN" ];
veyron.bodyGeometry.materials[ 2 ] = mlib[ "ChromeN" ];
veyron.wheelGeometry.materials[ 0 ] = mlib[ "ChromeN" ];
}
if ( gallardo.loaded ) {
gallardo.wheelGeometry.materials[ 0 ] = mlib[ "ChromeN" ];
}
} else {
if ( veyron.loaded ) {
veyron.bodyGeometry.materials[ 1 ] = mlib[ "Chrome" ];
veyron.bodyGeometry.materials[ 2 ] = mlib[ "Chrome" ];
veyron.wheelGeometry.materials[ 0 ] = mlib[ "Chrome" ];
}
if ( gallardo.loaded ) {
gallardo.wheelGeometry.materials[ 0 ] = mlib[ "Chrome" ];
}
}
effectBloom.screenUniforms[ "opacity" ].value = THREE.Math.mapLinear( vnorm, 0, 1, 1, 0.75 );
ambientLight.color.setHSV( 0, 0, THREE.Math.mapLinear( vnorm, 0, 1, 0.07, 0.33 ) );
groundBasic.color.setHSV( 0.1, 0.45, THREE.Math.mapLinear( vnorm, 0, 1, 0.725, 0.995 ) );
// blur
if ( blur ) {
effectSave.enabled = true;
effectBlend.enabled = true;
} else {
effectSave.enabled = false;
effectBlend.enabled = false;
}
// update car model
veyron.updateCarModel( delta, controlsVeyron );
gallardo.updateCarModel( delta, controlsGallardo );
// update camera
if ( ! FOLLOW_CAMERA ) {
cameraTarget.x = currentCar.root.position.x;
cameraTarget.z = currentCar.root.position.z;
} else {
spotLight.position.x = currentCar.root.position.x - 500;
spotLight.position.z = currentCar.root.position.z - 500;
}
// update shadows
spotLight.target.position.x = currentCar.root.position.x;
spotLight.target.position.z = currentCar.root.position.z;
// render cube map
var updateCubemap = true;
if ( updateCubemap ) {
veyron.setVisible( false );
gallardo.setVisible( false );
cubeCamera.updatePosition( currentCar.root.position );
renderer.autoClear = true;
cubeCamera.updateCubeMap( renderer, scene );
veyron.setVisible( true );
gallardo.setVisible( true );
}
// render scene
renderer.autoClear = false;
renderer.shadowMapEnabled = true;
camera.lookAt( cameraTarget );
renderer.clearTarget( null );
composer.render( 0.1 );
renderer.shadowMapEnabled = false;
}
</script>
</body>
</html>