|
@@ -24,7 +24,7 @@
|
|
let camera, scene, renderer;
|
|
let camera, scene, renderer;
|
|
let cameraControls;
|
|
let cameraControls;
|
|
let effectController;
|
|
let effectController;
|
|
- const teapotSize = 400;
|
|
|
|
|
|
+ const teapotSize = 300;
|
|
let ambientLight, light;
|
|
let ambientLight, light;
|
|
|
|
|
|
let tess = - 1; // force initialization
|
|
let tess = - 1; // force initialization
|
|
@@ -34,13 +34,9 @@
|
|
let bFitLid;
|
|
let bFitLid;
|
|
let bNonBlinn;
|
|
let bNonBlinn;
|
|
let shading;
|
|
let shading;
|
|
- let wireMaterial, flatMaterial, gouraudMaterial, phongMaterial, texturedMaterial, reflectiveMaterial;
|
|
|
|
|
|
|
|
let teapot, textureCube;
|
|
let teapot, textureCube;
|
|
-
|
|
|
|
- // allocate these just once
|
|
|
|
- const diffuseColor = new THREE.Color();
|
|
|
|
- const specularColor = new THREE.Color();
|
|
|
|
|
|
+ const materials = {};
|
|
|
|
|
|
init();
|
|
init();
|
|
render();
|
|
render();
|
|
@@ -58,10 +54,10 @@
|
|
camera.position.set( - 600, 550, 1300 );
|
|
camera.position.set( - 600, 550, 1300 );
|
|
|
|
|
|
// LIGHTS
|
|
// LIGHTS
|
|
- ambientLight = new THREE.AmbientLight( 0x333333 ); // 0.2
|
|
|
|
|
|
+ ambientLight = new THREE.AmbientLight( 0x333333 );
|
|
|
|
|
|
light = new THREE.DirectionalLight( 0xFFFFFF, 1.0 );
|
|
light = new THREE.DirectionalLight( 0xFFFFFF, 1.0 );
|
|
- // direction is set in GUI
|
|
|
|
|
|
+ light.position.set( 0.32, 0.39, 0.7 );
|
|
|
|
|
|
// RENDERER
|
|
// RENDERER
|
|
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
@@ -84,31 +80,18 @@
|
|
textureMap.encoding = THREE.sRGBEncoding;
|
|
textureMap.encoding = THREE.sRGBEncoding;
|
|
|
|
|
|
// REFLECTION MAP
|
|
// REFLECTION MAP
|
|
- const path = "textures/cube/pisa/";
|
|
|
|
- const urls = [
|
|
|
|
- path + "px.png", path + "nx.png",
|
|
|
|
- path + "py.png", path + "ny.png",
|
|
|
|
- path + "pz.png", path + "nz.png"
|
|
|
|
- ];
|
|
|
|
-
|
|
|
|
- textureCube = new THREE.CubeTextureLoader().load( urls );
|
|
|
|
- textureCube.encoding = THREE.sRGBEncoding;
|
|
|
|
-
|
|
|
|
- // MATERIALS
|
|
|
|
- const materialColor = new THREE.Color();
|
|
|
|
- materialColor.setRGB( 1.0, 1.0, 1.0 );
|
|
|
|
-
|
|
|
|
- wireMaterial = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe: true } );
|
|
|
|
-
|
|
|
|
- flatMaterial = new THREE.MeshPhongMaterial( { color: materialColor, specular: 0x000000, flatShading: true, side: THREE.DoubleSide } );
|
|
|
|
|
|
+ const path = 'textures/cube/pisa/';
|
|
|
|
+ const urls = [ 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' ];
|
|
|
|
|
|
- gouraudMaterial = new THREE.MeshLambertMaterial( { color: materialColor, side: THREE.DoubleSide } );
|
|
|
|
-
|
|
|
|
- phongMaterial = new THREE.MeshPhongMaterial( { color: materialColor, side: THREE.DoubleSide } );
|
|
|
|
-
|
|
|
|
- texturedMaterial = new THREE.MeshPhongMaterial( { color: materialColor, map: textureMap, side: THREE.DoubleSide } );
|
|
|
|
|
|
+ textureCube = new THREE.CubeTextureLoader().setPath( path ).load( urls );
|
|
|
|
+ textureCube.encoding = THREE.sRGBEncoding;
|
|
|
|
|
|
- reflectiveMaterial = new THREE.MeshPhongMaterial( { color: materialColor, envMap: textureCube, side: THREE.DoubleSide } );
|
|
|
|
|
|
+ materials[ 'wireframe' ] = new THREE.MeshBasicMaterial( { wireframe: true } );
|
|
|
|
+ materials[ 'flat' ] = new THREE.MeshPhongMaterial( { specular: 0x000000, flatShading: true, side: THREE.DoubleSide } );
|
|
|
|
+ materials[ 'smooth' ] = new THREE.MeshLambertMaterial( { side: THREE.DoubleSide } );
|
|
|
|
+ materials[ 'glossy' ] = new THREE.MeshPhongMaterial( { side: THREE.DoubleSide } );
|
|
|
|
+ materials[ 'textured' ] = new THREE.MeshPhongMaterial( { map: textureMap, side: THREE.DoubleSide } );
|
|
|
|
+ materials[ 'reflective' ] = new THREE.MeshPhongMaterial( { envMap: textureCube, side: THREE.DoubleSide } );
|
|
|
|
|
|
// scene itself
|
|
// scene itself
|
|
scene = new THREE.Scene();
|
|
scene = new THREE.Scene();
|
|
@@ -141,84 +124,23 @@
|
|
function setupGui() {
|
|
function setupGui() {
|
|
|
|
|
|
effectController = {
|
|
effectController = {
|
|
-
|
|
|
|
- shininess: 40.0,
|
|
|
|
- ka: 0.17,
|
|
|
|
- kd: 0.51,
|
|
|
|
- ks: 0.2,
|
|
|
|
- metallic: true,
|
|
|
|
-
|
|
|
|
- hue: 0.121,
|
|
|
|
- saturation: 0.73,
|
|
|
|
- lightness: 0.66,
|
|
|
|
-
|
|
|
|
- lhue: 0.04,
|
|
|
|
- lsaturation: 0.01, // non-zero so that fractions will be shown
|
|
|
|
- llightness: 1.0,
|
|
|
|
-
|
|
|
|
- // bizarrely, if you initialize these with negative numbers, the sliders
|
|
|
|
- // will not show any decimal places.
|
|
|
|
- lx: 0.32,
|
|
|
|
- ly: 0.39,
|
|
|
|
- lz: 0.7,
|
|
|
|
newTess: 15,
|
|
newTess: 15,
|
|
bottom: true,
|
|
bottom: true,
|
|
lid: true,
|
|
lid: true,
|
|
body: true,
|
|
body: true,
|
|
fitLid: false,
|
|
fitLid: false,
|
|
nonblinn: false,
|
|
nonblinn: false,
|
|
- newShading: "glossy"
|
|
|
|
|
|
+ newShading: 'glossy'
|
|
};
|
|
};
|
|
|
|
|
|
- let h;
|
|
|
|
-
|
|
|
|
const gui = new GUI();
|
|
const gui = new GUI();
|
|
-
|
|
|
|
- // material (attributes)
|
|
|
|
-
|
|
|
|
- h = gui.addFolder( "Material control" );
|
|
|
|
-
|
|
|
|
- h.add( effectController, "shininess", 1.0, 400.0, 1.0 ).name( "shininess" ).onChange( render );
|
|
|
|
- h.add( effectController, "kd", 0.0, 1.0, 0.025 ).name( "diffuse strength" ).onChange( render );
|
|
|
|
- h.add( effectController, "ks", 0.0, 1.0, 0.025 ).name( "specular strength" ).onChange( render );
|
|
|
|
- h.add( effectController, "metallic" ).onChange( render );
|
|
|
|
-
|
|
|
|
- // material (color)
|
|
|
|
-
|
|
|
|
- h = gui.addFolder( "Material color" );
|
|
|
|
-
|
|
|
|
- h.add( effectController, "hue", 0.0, 1.0, 0.025 ).name( "hue" ).onChange( render );
|
|
|
|
- h.add( effectController, "saturation", 0.0, 1.0, 0.025 ).name( "saturation" ).onChange( render );
|
|
|
|
- h.add( effectController, "lightness", 0.0, 1.0, 0.025 ).name( "lightness" ).onChange( render );
|
|
|
|
-
|
|
|
|
- // light (point)
|
|
|
|
-
|
|
|
|
- h = gui.addFolder( "Lighting" );
|
|
|
|
-
|
|
|
|
- h.add( effectController, "lhue", 0.0, 1.0, 0.025 ).name( "hue" ).onChange( render );
|
|
|
|
- h.add( effectController, "lsaturation", 0.0, 1.0, 0.025 ).name( "saturation" ).onChange( render );
|
|
|
|
- h.add( effectController, "llightness", 0.0, 1.0, 0.025 ).name( "lightness" ).onChange( render );
|
|
|
|
- h.add( effectController, "ka", 0.0, 1.0, 0.025 ).name( "ambient" ).onChange( render );
|
|
|
|
-
|
|
|
|
- // light (directional)
|
|
|
|
-
|
|
|
|
- h = gui.addFolder( "Light direction" );
|
|
|
|
-
|
|
|
|
- h.add( effectController, "lx", - 1.0, 1.0, 0.025 ).name( "x" ).onChange( render );
|
|
|
|
- h.add( effectController, "ly", - 1.0, 1.0, 0.025 ).name( "y" ).onChange( render );
|
|
|
|
- h.add( effectController, "lz", - 1.0, 1.0, 0.025 ).name( "z" ).onChange( render );
|
|
|
|
-
|
|
|
|
- h = gui.addFolder( "Tessellation control" );
|
|
|
|
- h.add( effectController, "newTess", [ 2, 3, 4, 5, 6, 8, 10, 15, 20, 30, 40, 50 ] ).name( "Tessellation Level" ).onChange( render );
|
|
|
|
- h.add( effectController, "lid" ).name( "display lid" ).onChange( render );
|
|
|
|
- h.add( effectController, "body" ).name( "display body" ).onChange( render );
|
|
|
|
- h.add( effectController, "bottom" ).name( "display bottom" ).onChange( render );
|
|
|
|
- h.add( effectController, "fitLid" ).name( "snug lid" ).onChange( render );
|
|
|
|
- h.add( effectController, "nonblinn" ).name( "original scale" ).onChange( render );
|
|
|
|
-
|
|
|
|
- // shading
|
|
|
|
-
|
|
|
|
- gui.add( effectController, "newShading", [ "wireframe", "flat", "smooth", "glossy", "textured", "reflective" ] ).name( "Shading" ).onChange( render );
|
|
|
|
|
|
+ gui.add( effectController, 'newTess', [ 2, 3, 4, 5, 6, 8, 10, 15, 20, 30, 40, 50 ] ).name( 'Tessellation Level' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'lid' ).name( 'display lid' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'body' ).name( 'display body' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'bottom' ).name( 'display bottom' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'fitLid' ).name( 'snug lid' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'nonblinn' ).name( 'original scale' ).onChange( render );
|
|
|
|
+ gui.add( effectController, 'newShading', [ 'wireframe', 'flat', 'smooth', 'glossy', 'textured', 'reflective' ] ).name( 'Shading' ).onChange( render );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -247,42 +169,8 @@
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // We're a bit lazy here. We could check to see if any material attributes changed and update
|
|
|
|
- // only if they have. But, these calls are cheap enough and this is just a demo.
|
|
|
|
- phongMaterial.shininess = effectController.shininess;
|
|
|
|
- texturedMaterial.shininess = effectController.shininess;
|
|
|
|
-
|
|
|
|
- diffuseColor.setHSL( effectController.hue, effectController.saturation, effectController.lightness );
|
|
|
|
- if ( effectController.metallic ) {
|
|
|
|
-
|
|
|
|
- // make colors match to give a more metallic look
|
|
|
|
- specularColor.copy( diffuseColor );
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- // more of a plastic look
|
|
|
|
- specularColor.setRGB( 1, 1, 1 );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- diffuseColor.multiplyScalar( effectController.kd );
|
|
|
|
- flatMaterial.color.copy( diffuseColor );
|
|
|
|
- gouraudMaterial.color.copy( diffuseColor );
|
|
|
|
- phongMaterial.color.copy( diffuseColor );
|
|
|
|
- texturedMaterial.color.copy( diffuseColor );
|
|
|
|
-
|
|
|
|
- specularColor.multiplyScalar( effectController.ks );
|
|
|
|
- phongMaterial.specular.copy( specularColor );
|
|
|
|
- texturedMaterial.specular.copy( specularColor );
|
|
|
|
-
|
|
|
|
- // Ambient's actually controlled by the light for this demo
|
|
|
|
- ambientLight.color.setHSL( effectController.hue, effectController.saturation, effectController.lightness * effectController.ka );
|
|
|
|
-
|
|
|
|
- light.position.set( effectController.lx, effectController.ly, effectController.lz );
|
|
|
|
- light.color.setHSL( effectController.lhue, effectController.lsaturation, effectController.llightness );
|
|
|
|
-
|
|
|
|
// skybox is rendered separately, so that it is always behind the teapot.
|
|
// skybox is rendered separately, so that it is always behind the teapot.
|
|
- if ( shading === "reflective" ) {
|
|
|
|
|
|
+ if ( shading === 'reflective' ) {
|
|
|
|
|
|
scene.background = textureCube;
|
|
scene.background = textureCube;
|
|
|
|
|
|
@@ -306,7 +194,7 @@
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- const teapotGeometry = new TeapotGeometry( teapotSize,
|
|
|
|
|
|
+ const geometry = new TeapotGeometry( teapotSize,
|
|
tess,
|
|
tess,
|
|
effectController.bottom,
|
|
effectController.bottom,
|
|
effectController.lid,
|
|
effectController.lid,
|
|
@@ -314,13 +202,7 @@
|
|
effectController.fitLid,
|
|
effectController.fitLid,
|
|
! effectController.nonblinn );
|
|
! effectController.nonblinn );
|
|
|
|
|
|
- teapot = new THREE.Mesh(
|
|
|
|
- teapotGeometry,
|
|
|
|
- shading === "wireframe" ? wireMaterial : (
|
|
|
|
- shading === "flat" ? flatMaterial : (
|
|
|
|
- shading === "smooth" ? gouraudMaterial : (
|
|
|
|
- shading === "glossy" ? phongMaterial : (
|
|
|
|
- shading === "textured" ? texturedMaterial : reflectiveMaterial ) ) ) ) ); // if no match, pick Phong
|
|
|
|
|
|
+ teapot = new THREE.Mesh( geometry, materials[ shading ] );
|
|
|
|
|
|
scene.add( teapot );
|
|
scene.add( teapot );
|
|
|
|
|