|
@@ -1,7 +1,7 @@
|
|
<!DOCTYPE html>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<html lang="en">
|
|
<head>
|
|
<head>
|
|
- <title>three.js webgl - lights - rect light</title>
|
|
|
|
|
|
+ <title>three.js webgl - lights - rect area light</title>
|
|
<meta charset="utf-8">
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
<style>
|
|
<style>
|
|
@@ -35,7 +35,7 @@
|
|
|
|
|
|
<div id="container"></div>
|
|
<div id="container"></div>
|
|
<div id="info">
|
|
<div id="info">
|
|
- <a href="http://threejs.org" target="_blank">three.js</a> - Demo of RectAreaLight on Phong and Standard Material Meshes - by <a href="http://github.com/abelnation" target="_blank">abelnation</a><br />
|
|
|
|
|
|
+ <a href="http://threejs.org" target="_blank">three.js</a> - Demo of RectAreaLight - by <a href="http://github.com/abelnation" target="_blank">abelnation</a><br />
|
|
Click and drag to move OrbitControls.<br />
|
|
Click and drag to move OrbitControls.<br />
|
|
<br />
|
|
<br />
|
|
</div>
|
|
</div>
|
|
@@ -54,24 +54,17 @@
|
|
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
|
|
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
|
|
|
|
|
|
var rnd = new THREE.WebGLRenderer();
|
|
var rnd = new THREE.WebGLRenderer();
|
|
- var cam = new THREE.PerspectiveCamera( 34, window.innerWidth / window.innerHeight, 0.1, 20000 );
|
|
|
|
|
|
+ var cam = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
|
|
var orb = new THREE.OrbitControls( cam, rnd.domElement );
|
|
var orb = new THREE.OrbitControls( cam, rnd.domElement );
|
|
|
|
|
|
var scn = new THREE.Scene();
|
|
var scn = new THREE.Scene();
|
|
var origin = new THREE.Object3D();
|
|
var origin = new THREE.Object3D();
|
|
|
|
|
|
- var matPhongParams = {
|
|
|
|
- specular: 0xFFFFFF,
|
|
|
|
- shininess: 1000
|
|
|
|
- };
|
|
|
|
var matStdParams = {
|
|
var matStdParams = {
|
|
roughness: 0.044676705160855, // calculated from shininess = 1000
|
|
roughness: 0.044676705160855, // calculated from shininess = 1000
|
|
metalness: 0.0
|
|
metalness: 0.0
|
|
};
|
|
};
|
|
|
|
|
|
- var matPhongFloor = new THREE.MeshPhongMaterial( matPhongParams );
|
|
|
|
- var matPhongObjects = new THREE.MeshPhongMaterial( matPhongParams );
|
|
|
|
-
|
|
|
|
var matStdFloor = new THREE.MeshStandardMaterial( matStdParams );
|
|
var matStdFloor = new THREE.MeshStandardMaterial( matStdParams );
|
|
var matStdObjects = new THREE.MeshStandardMaterial( matStdParams );
|
|
var matStdObjects = new THREE.MeshStandardMaterial( matStdParams );
|
|
|
|
|
|
@@ -80,17 +73,12 @@
|
|
var geoSphere = new THREE.SphereGeometry( 1.5, 32, 32 );
|
|
var geoSphere = new THREE.SphereGeometry( 1.5, 32, 32 );
|
|
var geoKnot = new THREE.TorusKnotGeometry( 1.5, 0.5, 100, 16 );
|
|
var geoKnot = new THREE.TorusKnotGeometry( 1.5, 0.5, 100, 16 );
|
|
|
|
|
|
- var mshPhongFloor = new THREE.Mesh( geoFloor, matPhongFloor );
|
|
|
|
- var mshPhongBox = new THREE.Mesh( geoBox, matPhongObjects );
|
|
|
|
- var mshPhongSphere = new THREE.Mesh( geoSphere, matPhongObjects );
|
|
|
|
- var mshPhongKnot = new THREE.Mesh( geoKnot, matPhongObjects );
|
|
|
|
-
|
|
|
|
var mshStdFloor = new THREE.Mesh( geoFloor, matStdFloor );
|
|
var mshStdFloor = new THREE.Mesh( geoFloor, matStdFloor );
|
|
var mshStdBox = new THREE.Mesh( geoBox, matStdObjects );
|
|
var mshStdBox = new THREE.Mesh( geoBox, matStdObjects );
|
|
var mshStdSphere = new THREE.Mesh( geoSphere, matStdObjects );
|
|
var mshStdSphere = new THREE.Mesh( geoSphere, matStdObjects );
|
|
var mshStdKnot = new THREE.Mesh( geoKnot, matStdObjects );
|
|
var mshStdKnot = new THREE.Mesh( geoKnot, matStdObjects );
|
|
|
|
|
|
- var amb = new THREE.AmbientLight( 0x000000 );
|
|
|
|
|
|
+ var amb = new THREE.AmbientLight( 0xffffff, 0.0 );
|
|
|
|
|
|
var rectLight;
|
|
var rectLight;
|
|
var rectLightHelper;
|
|
var rectLightHelper;
|
|
@@ -126,13 +114,10 @@
|
|
|
|
|
|
cam.position.set( 0, 20, 45 );
|
|
cam.position.set( 0, 20, 45 );
|
|
|
|
|
|
- rectLight = new THREE.RectAreaLight( 0xFFFFFF, undefined, 2, 10 );
|
|
|
|
- rectLight.matrixAutoUpdate = true;
|
|
|
|
- rectLight.intensity = 80.0;
|
|
|
|
|
|
+ rectLight = new THREE.RectAreaLight( 0xffffff, 100, 10, 10 );
|
|
rectLight.position.set( 5, 5, 0 );
|
|
rectLight.position.set( 5, 5, 0 );
|
|
|
|
|
|
// TODO: ensure RectAreaLight handles target param correctly
|
|
// TODO: ensure RectAreaLight handles target param correctly
|
|
- // rectLight.target = mshPhongBox;
|
|
|
|
|
|
|
|
rectLightHelper = new THREE.RectAreaLightHelper( rectLight );
|
|
rectLightHelper = new THREE.RectAreaLightHelper( rectLight );
|
|
scn.add( rectLightHelper );
|
|
scn.add( rectLightHelper );
|
|
@@ -142,42 +127,19 @@
|
|
scn.add( cam );
|
|
scn.add( cam );
|
|
scn.add( origin );
|
|
scn.add( origin );
|
|
|
|
|
|
- matPhongFloor.color.set( 0x808080 );
|
|
|
|
- matPhongObjects.color.set( 0xA00000 );
|
|
|
|
matStdFloor.color.set( 0x808080 );
|
|
matStdFloor.color.set( 0x808080 );
|
|
matStdObjects.color.set( 0xA00000 );
|
|
matStdObjects.color.set( 0xA00000 );
|
|
|
|
|
|
- mshPhongFloor.receiveShadow = true;
|
|
|
|
- mshPhongFloor.position.set( 0, 0, 0 );
|
|
|
|
-
|
|
|
|
- mshPhongBox.castShadow = true;
|
|
|
|
- mshPhongBox.receiveShadow = true;
|
|
|
|
- mshPhongBox.position.set( 0, 5, 5 );
|
|
|
|
- mshPhongBox.rotation.set( 0, Math.PI / 2.0, 0 );
|
|
|
|
-
|
|
|
|
- mshPhongSphere.castShadow = true;
|
|
|
|
- mshPhongSphere.receiveShadow = true;
|
|
|
|
- mshPhongSphere.position.set(-5, 5, 5 );
|
|
|
|
-
|
|
|
|
- mshPhongKnot.position.set( 5, 5, 5 );
|
|
|
|
- mshPhongKnot.castShadow = true;
|
|
|
|
- mshPhongKnot.receiveShadow = true;
|
|
|
|
-
|
|
|
|
- scn.add( mshPhongFloor );
|
|
|
|
- scn.add( mshPhongBox );
|
|
|
|
- scn.add( mshPhongSphere );
|
|
|
|
- scn.add( mshPhongKnot );
|
|
|
|
-
|
|
|
|
mshStdBox.castShadow = true;
|
|
mshStdBox.castShadow = true;
|
|
mshStdBox.receiveShadow = true;
|
|
mshStdBox.receiveShadow = true;
|
|
- mshStdBox.position.set( 0, 5, -5 );
|
|
|
|
|
|
+ mshStdBox.position.set( 0, 5, 0 );
|
|
mshStdBox.rotation.set( 0, Math.PI / 2.0, 0 );
|
|
mshStdBox.rotation.set( 0, Math.PI / 2.0, 0 );
|
|
|
|
|
|
mshStdSphere.castShadow = true;
|
|
mshStdSphere.castShadow = true;
|
|
mshStdSphere.receiveShadow = true;
|
|
mshStdSphere.receiveShadow = true;
|
|
- mshStdSphere.position.set(-5, 5, -5 );
|
|
|
|
|
|
+ mshStdSphere.position.set( -5, 5, 0 );
|
|
|
|
|
|
- mshStdKnot.position.set( 5, 5, -5 );
|
|
|
|
|
|
+ mshStdKnot.position.set( 5, 5, 0 );
|
|
mshStdKnot.castShadow = true;
|
|
mshStdKnot.castShadow = true;
|
|
mshStdKnot.receiveShadow = true;
|
|
mshStdKnot.receiveShadow = true;
|
|
|
|
|
|
@@ -191,12 +153,14 @@
|
|
scn.add( rectLight );
|
|
scn.add( rectLight );
|
|
|
|
|
|
document.body.appendChild( rnd.domElement );
|
|
document.body.appendChild( rnd.domElement );
|
|
|
|
+
|
|
onResize();
|
|
onResize();
|
|
- window.addEventListener( 'resize', onResize, false );
|
|
|
|
|
|
|
|
- orb.addEventListener( 'change', render );
|
|
|
|
|
|
+ orb.target.copy( mshStdBox.position );
|
|
orb.update();
|
|
orb.update();
|
|
|
|
|
|
|
|
+ window.addEventListener( 'resize', onResize, false );
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
function onResize() {
|
|
function onResize() {
|
|
@@ -204,7 +168,6 @@
|
|
rnd.setSize( window.innerWidth, window.innerHeight );
|
|
rnd.setSize( window.innerWidth, window.innerHeight );
|
|
cam.aspect = ( window.innerWidth / window.innerHeight );
|
|
cam.aspect = ( window.innerWidth / window.innerHeight );
|
|
cam.updateProjectionMatrix();
|
|
cam.updateProjectionMatrix();
|
|
- orb.target = mshPhongBox.position;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -221,14 +184,6 @@
|
|
|
|
|
|
function update() {
|
|
function update() {
|
|
|
|
|
|
- var dt = 6000;
|
|
|
|
- var qdt = dt / 4.0;
|
|
|
|
- var dirSigns = [
|
|
|
|
- [ 1, 1 ],
|
|
|
|
- [ - 1, 1 ],
|
|
|
|
- [ - 1, 1 ],
|
|
|
|
- [ 1, 1 ]
|
|
|
|
- ];
|
|
|
|
var t = ( Date.now() / 1000 );
|
|
var t = ( Date.now() / 1000 );
|
|
|
|
|
|
// move light in circle around center
|
|
// move light in circle around center
|
|
@@ -243,7 +198,6 @@
|
|
|
|
|
|
rectLight.position.set( lx, ly, lz );
|
|
rectLight.position.set( lx, ly, lz );
|
|
rectLight.lookAt( origin.position );
|
|
rectLight.lookAt( origin.position );
|
|
- rectLight.updateMatrixWorld();
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -259,24 +213,14 @@
|
|
if ( gui ) gui.destroy();
|
|
if ( gui ) gui.destroy();
|
|
|
|
|
|
gui = new dat.GUI();
|
|
gui = new dat.GUI();
|
|
- gui.width = 190;
|
|
|
|
var gStyle = gui.domElement.style;
|
|
var gStyle = gui.domElement.style;
|
|
gStyle.position = "absolute";
|
|
gStyle.position = "absolute";
|
|
gStyle.top = "48px";
|
|
gStyle.top = "48px";
|
|
- gStyle.height = "220px";
|
|
|
|
|
|
|
|
gui.open();
|
|
gui.open();
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- function blinnToGGX( blinnExp ) {
|
|
|
|
- return Math.sqrt( 2.0 / ( blinnExp + 2.0 ) );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function GGXToBlinn( roughness ) {
|
|
|
|
- return ( 2.0 / Math.pow( roughness + 0.0001, 2 ) - 2.0 );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
function buildGui() {
|
|
function buildGui() {
|
|
|
|
|
|
clearGui();
|
|
clearGui();
|
|
@@ -287,27 +231,25 @@
|
|
height: rectLight.height,
|
|
height: rectLight.height,
|
|
color: rectLight.color.getHex(),
|
|
color: rectLight.color.getHex(),
|
|
intensity: rectLight.intensity,
|
|
intensity: rectLight.intensity,
|
|
- 'ambient light color': amb.color.getHex(),
|
|
|
|
- 'floor color p': matPhongFloor.color.getHex(),
|
|
|
|
- 'object color p': matPhongObjects.color.getHex(),
|
|
|
|
- 'shininess p': matPhongFloor.shininess,
|
|
|
|
- 'floor color s': matStdFloor.color.getHex(),
|
|
|
|
- 'object color s': matStdObjects.color.getHex(),
|
|
|
|
- 'roughness s': matStdFloor.roughness,
|
|
|
|
- 'metalness s': matStdFloor.metalness,
|
|
|
|
|
|
+ 'ambient': amb.intensity,
|
|
|
|
+ 'floor color': matStdFloor.color.getHex(),
|
|
|
|
+ 'object color': matStdObjects.color.getHex(),
|
|
|
|
+ 'roughness': matStdFloor.roughness,
|
|
|
|
+ 'metalness': matStdFloor.metalness,
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
gui.add( param, 'motion' );
|
|
gui.add( param, 'motion' );
|
|
|
|
|
|
var lightFolder = gui.addFolder( 'Light' );
|
|
var lightFolder = gui.addFolder( 'Light' );
|
|
- lightFolder.add( param, 'width', 0.1, 20).onChange( function ( val ) {
|
|
|
|
|
|
+
|
|
|
|
+ lightFolder.add( param, 'width', 0.1, 20 ).onChange( function ( val ) {
|
|
|
|
|
|
rectLight.width = val;
|
|
rectLight.width = val;
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- lightFolder.add( param, 'height', 0.1, 20).onChange( function ( val ) {
|
|
|
|
|
|
+ lightFolder.add( param, 'height', 0.1, 20 ).onChange( function ( val ) {
|
|
|
|
|
|
rectLight.height = val;
|
|
rectLight.height = val;
|
|
|
|
|
|
@@ -319,70 +261,51 @@
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- lightFolder.add( param, 'intensity', 0.0, 200.0 ).onChange( function ( val ) {
|
|
|
|
|
|
+ lightFolder.add( param, 'intensity', 0.0, 400.0 ).onChange( function ( val ) {
|
|
|
|
|
|
rectLight.intensity = val;
|
|
rectLight.intensity = val;
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- lightFolder.addColor( param, 'ambient light color' ).onChange( function ( val ) {
|
|
|
|
-
|
|
|
|
- amb.color.setHex( val );
|
|
|
|
-
|
|
|
|
- } );
|
|
|
|
-
|
|
|
|
- var phongFolder = gui.addFolder( 'Phong Material' );
|
|
|
|
- phongFolder.addColor( param, 'floor color p' ).onChange( function ( val ) {
|
|
|
|
-
|
|
|
|
- matPhongFloor.color.setHex( val );
|
|
|
|
-
|
|
|
|
- } );
|
|
|
|
-
|
|
|
|
- phongFolder.addColor( param, 'object color p' ).onChange( function ( val ) {
|
|
|
|
|
|
+ lightFolder.add( param, 'ambient', 0.0, 0.05 ).onChange( function ( val ) {
|
|
|
|
|
|
- matPhongObjects.color.setHex( val );
|
|
|
|
|
|
+ amb.intensity = val;
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- phongFolder.add( param, 'shininess p', 0.0, 1000.0 ).listen().onChange( function ( val ) {
|
|
|
|
-
|
|
|
|
- matPhongObjects.shininess = val;
|
|
|
|
- matPhongFloor.shininess = val;
|
|
|
|
-
|
|
|
|
- param['roughness s'] = blinnToGGX( val );
|
|
|
|
-
|
|
|
|
- } );
|
|
|
|
|
|
+ lightFolder.open();
|
|
|
|
|
|
var standardFolder = gui.addFolder( 'Standard Material' );
|
|
var standardFolder = gui.addFolder( 'Standard Material' );
|
|
- standardFolder.addColor( param, 'floor color s' ).onChange( function ( val ) {
|
|
|
|
|
|
+
|
|
|
|
+ standardFolder.addColor( param, 'floor color' ).onChange( function ( val ) {
|
|
|
|
|
|
matStdFloor.color.setHex( val );
|
|
matStdFloor.color.setHex( val );
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- standardFolder.addColor( param, 'object color s' ).onChange( function ( val ) {
|
|
|
|
|
|
+ standardFolder.addColor( param, 'object color' ).onChange( function ( val ) {
|
|
|
|
|
|
matStdObjects.color.setHex( val );
|
|
matStdObjects.color.setHex( val );
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- standardFolder.add( param, 'roughness s', 0.0, 1.0 ).listen().onChange( function ( val ) {
|
|
|
|
|
|
+ standardFolder.add( param, 'roughness', 0.0, 1.0 ).onChange( function ( val ) {
|
|
|
|
|
|
matStdObjects.roughness = val;
|
|
matStdObjects.roughness = val;
|
|
matStdFloor.roughness = val;
|
|
matStdFloor.roughness = val;
|
|
|
|
|
|
- param['shininess p'] = GGXToBlinn( val );
|
|
|
|
-
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
// TODO (abelnation): use env map to reflect metal property
|
|
// TODO (abelnation): use env map to reflect metal property
|
|
- standardFolder.add( param, 'metalness s', 0.0, 1.0 ).onChange( function ( val ) {
|
|
|
|
|
|
+ standardFolder.add( param, 'metalness', 0.0, 1.0 ).onChange( function ( val ) {
|
|
|
|
|
|
matStdObjects.metalness = val;
|
|
matStdObjects.metalness = val;
|
|
matStdFloor.metalness = val;
|
|
matStdFloor.metalness = val;
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
+ standardFolder.open();
|
|
|
|
+
|
|
// TODO: rect area light distance
|
|
// TODO: rect area light distance
|
|
// TODO: rect area light decay
|
|
// TODO: rect area light decay
|
|
|
|
|