commit 138fbfbc508ba33dc1aaaff21ccf398b1f397993
parent 31d661d2569d27b998d37caabf2fea8b7f362965
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Mon, 8 Jul 2024 12:53:40 -0300
set up shadow maps for all objects in scene
Diffstat:
4 files changed, 155 insertions(+), 28 deletions(-)
diff --git a/tp/src/bridge.js b/tp/src/bridge.js
@@ -258,6 +258,9 @@ export function generateBridge(arcCount=1, arcRadius=3,
*/
const bridgeColumns = new THREE.Mesh(bridgeColumnsGeometry, bridgeMaterial);
+ bridgeColumns.castShadow = true;
+ bridgeColumns.receiveShadow = true;
+
bridge.add(bridgeColumns);
// para reutilizar la textura de ladrillos usada en los arcos se escalan las
@@ -270,6 +273,9 @@ export function generateBridge(arcCount=1, arcRadius=3,
const bridgeRoadway = new THREE.Mesh(bridgeRoadwayGeometry, bridgeMaterial);
bridge.add(bridgeRoadway);
+ bridgeRoadway.castShadow = true;
+ bridgeRoadway.receiveShadow = true;
+
const cageGeometry = generateBridgeCage(squaresCount)
cageGeometry.translate(0, bridgeHeight+roadwayHeight-squareTubeRadius*2, 0);
@@ -282,6 +288,10 @@ export function generateBridge(arcCount=1, arcRadius=3,
});
const bridgeCage = new THREE.Mesh(cageGeometry, cageMaterial);
+
+ bridgeCage.castShadow = true;
+ bridgeCage.receiveShadow = true;
+
bridge.add(bridgeCage);
const roadwayFloorGeometry = new THREE.BoxGeometry(
@@ -306,6 +316,9 @@ export function generateBridge(arcCount=1, arcRadius=3,
});
const roadwayFloor = new THREE.Mesh(roadwayFloorGeometry, roadwayFloorMaterial);
+ roadwayFloor.receiveShadow = true;
+ roadwayFloor.castShadow = false;
+
bridge.add(roadwayFloor)
return bridge;
}
diff --git a/tp/src/scene.js b/tp/src/scene.js
@@ -24,6 +24,7 @@ let firstPersonControls, orbitControls;
let train, trainLight, trainLight2, trainLight3;
+let helpers = [];
let cameras = [];
let objects = [];
let lights = {
@@ -294,7 +295,10 @@ function setupThreeJs() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
- document.body.appendChild( renderer.domElement );
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
+ renderer.shadowMap.enabled = true;
+
+ document.body.appendChild(renderer.domElement);
const topView = new THREE.PerspectiveCamera(
35, window.innerWidth / window.innerHeight, 0.1, 1000);
@@ -312,7 +316,19 @@ function setupThreeJs() {
lights.directional.object = new THREE.DirectionalLight(0xffffff, 1);
lights.directional.object.position.set(-100, 100, 100);
-
+ // Set up shadow properties for the light
+ lights.directional.object.castShadow = true; // default false
+ lights.directional.object.shadow.mapSize.width = 512; // default
+ lights.directional.object.shadow.mapSize.height = 512; // default
+
+ lights.directional.object.shadow.camera = new THREE.OrthographicCamera(
+ -65, 65, 65, -40, 0.5, 225);
+
+ const directionalLightShadowsHelper = new THREE.CameraHelper(lights.directional.object.shadow.camera);
+ directionalLightShadowsHelper.visible = settings.showHelpers;
+ scene.add(directionalLightShadowsHelper);
+ helpers.push(directionalLightShadowsHelper);
+
scene.add(lights.ambient.object);
scene.add(lights.hemisphere.object);
scene.add(lights.directional.object);
@@ -332,17 +348,22 @@ function setupThreeJs() {
lights.directional.object.position.set(-100, 100, 100);
}
- const helper = new THREE.HemisphereLightHelper(lights.hemisphere.object, 5);
- if(settings.showHelpers) scene.add(helper) ;
+ const hemisphereLightHelper = new THREE.HemisphereLightHelper(lights.hemisphere.object, 5);
+ helpers.push(hemisphereLightHelper);
- const directinoalLightHelper = new THREE.DirectionalLightHelper( lights.directional.object, 5);
- if(settings.showHelpers) scene.add(directinoalLightHelper);
+ const directionalLightHelper = new THREE.DirectionalLightHelper(lights.directional.object, 5);
+ helpers.push(directionalLightHelper);
const gridHelper = new THREE.GridHelper(200, 200);
- if(settings.showHelpers) scene.add(gridHelper);
+ helpers.push(gridHelper);
const axesHelper = new THREE.AxesHelper(5);
- if(settings.showHelpers) scene.add(axesHelper);
+ helpers.push(axesHelper);
+
+ for(let i = 0; i < helpers.length; ++i) {
+ helpers[i].visible = settings.showHelpers;
+ scene.add(helpers[i]);
+ }
window.addEventListener('resize', onResize);
onResize();
@@ -411,6 +432,11 @@ function buildBridge() {
bridgeCamera.name = "bridgeCamera";
cameras.push(bridgeCamera);
+ bridge1.castShadow = true;
+ bridge1.receiveShadow = true;
+ bridge2.castShadow = true;
+ bridge2.receiveShadow = true;
+
scene.add(bridge1);
scene.add(bridge2);
@@ -450,27 +476,54 @@ function buildLoco() {
cameras.push(trainBackCamera);
// SpotLight(color: Int, intensity: Float, distance: Float, angle: Radians, penumbra: Float, decay: Float)
- trainLight = new THREE.SpotLight(0xffffff, 100.0, 2000.0, Math.PI/3, 0.5, 0.5);
+ trainLight = new THREE.SpotLight(0xffffff, 200.0, 100.0, Math.PI/6, 0.5, 1.0);
train.add(trainLight.target);
train.add(trainLight);
- trainLight.position.set(0, 2, 15);
- trainLight.target.position.set(0, -100, 100);
+ trainLight.position.set(0, 4, 5);
+ trainLight.target.position.set(0, -100, 1000);
trainLight.target.updateMatrixWorld();
- trainLight2 = new THREE.SpotLight(0xffffff, 10.0, 4.0, Math.PI/2, 0.5, 0.5);
- train.add(trainLight2.target);
- train.add(trainLight2);
- trainLight2.position.set(0, 5, 20);
+ trainLight2 = new THREE.SpotLight(0xffffff, 10.0, 3.0, Math.PI/6, 0.5, 0.5);
+ // train.add(trainLight2.target);
+ // train.add(trainLight2);
+ trainLight2.position.set(0, 3.25, 15);
trainLight2.target.position.set(0, 0, -100);
trainLight2.target.updateMatrixWorld();
- trainLight3 = new THREE.SpotLight(0xffffff, 10.0, 10.0, Math.PI/2, 0.5, 0.5);
+ trainLight3 = new THREE.SpotLight(0xffffff, 10.0, 16.0, Math.PI/3, 0.5, 0.5);
train.add(trainLight3.target);
train.add(trainLight3);
- trainLight3.position.set(0, 5, 10);
- trainLight3.target.position.set(0, 0, 100);
+ trainLight3.position.set(0, 5, 5);
+ trainLight3.target.position.set(0, -25, 100);
trainLight3.target.updateMatrixWorld();
+ //Set up shadow properties for the light
+ trainLight.castShadow = true; // default false
+ trainLight.shadow.mapSize.width = 128; // default
+ trainLight.shadow.mapSize.height = 128; // default
+ trainLight.shadow.camera.near = 0.5; // default
+ trainLight.shadow.camera.far = 40; // default
+ trainLight.shadow.focus = 1; // default
+
+ trainLight3.castShadow = true; // default false
+ trainLight3.shadow.mapSize.width = 512; // default
+ trainLight3.shadow.mapSize.height = 512; // default
+ trainLight3.shadow.camera.near = 0.5; // default
+ trainLight3.shadow.camera.far = 100; // default
+ trainLight3.shadow.focus = 1; // default
+
+ const trainLightHelper = new THREE.CameraHelper(trainLight.shadow.camera);
+ const trainLight2Helper = new THREE.CameraHelper(trainLight2.shadow.camera);
+ const trainLight3Helper = new THREE.CameraHelper(trainLight3.shadow.camera);
+
+ trainLightHelper.visible = settings.showHelpers;
+ trainLight2Helper.visible = settings.showHelpers;
+ trainLight3Helper.visible = settings.showHelpers;
+
+ helpers.push(trainLightHelper);
+ helpers.push(trainLight2Helper);
+ helpers.push(trainLight3Helper);
+
train.scale.set(0.145, 0.145, 0.145);
train.visible = settings.showTrain;
scene.add(train);
@@ -485,11 +538,11 @@ function buildRailsFoundation() {
textures.durmientes.object.anisotropy = 16;
// load into `map` the example texture
- const map = new THREE.TextureLoader().load(
- 'https://threejs.org/examples/textures/uv_grid_opengl.jpg');
- map.wrapS = map.wrapT = THREE.RepeatWrapping;
- map.repeat.set(1, 80);
- map.anisotropy = 16;
+ // const map = new THREE.TextureLoader().load(
+ // 'https://threejs.org/examples/textures/uv_grid_opengl.jpg');
+ // map.wrapS = map.wrapT = THREE.RepeatWrapping;
+ // map.repeat.set(1, 80);
+ // map.anisotropy = 16;
// map.rotation = Math.PI/2;
const railsFoundationMaterial = new THREE.MeshPhongMaterial({
@@ -502,6 +555,8 @@ function buildRailsFoundation() {
});
const railsFoundation = new THREE.Mesh(railsFoundationGeometry, railsFoundationMaterial);
+ railsFoundation.receiveShadow = true;
+ railsFoundation.castShadow = true;
railsFoundation.position.set(-1, 1.25, -1);
railsFoundation.scale.set(1.00, 1.50, 1.00);
scene.add(railsFoundation);
@@ -521,6 +576,8 @@ function buildRails() {
});
const rails = new THREE.Mesh(railsGeometry, railsMaterial);
+ rails.castShadow = true;
+ rails.receiveShadow = true;
rails.position.set(-1, 1.25, -1);
rails.scale.set(1.00, 1.50, 1.00);
scene.add(rails);
@@ -697,6 +754,8 @@ function buildTerrain() {
const customMaterial = buildTerrainCustomMaterial();
terrain = new THREE.Mesh(terrainGeometry, customMaterial);
+ terrain.receiveShadow = true;
+
scene.add(terrain);
terrain.position.set(0, amplitudeBottom, 0);
@@ -708,6 +767,9 @@ function buildTerrain() {
const water = new THREE.Mesh( waterGeometry, waterMaterial );
water.rotateX(Math.PI/2);
water.position.set(0, 0, -0.65);
+
+ water.castShadow = false;
+ water.receiveShadow = true;
scene.add(water);
}
@@ -729,6 +791,8 @@ function buildTunnel() {
});
const tunnel = new THREE.Mesh(tunnelGeometry, tunnelMaterial) ;
+ tunnel.castShadow = true;
+ tunnel.receiveShadow = true;
tunnel.scale.set(0.5, 0.5, 0.5);
const trainPathPos = getRailsPathPosAt(0.32);
@@ -751,6 +815,11 @@ function buildTrees(count = 50) {
const [treeLogs, treeLeaves] = createInstancedTrees(count);
scene.add(treeLogs);
scene.add(treeLeaves);
+
+ treeLogs.castShadow = true;
+ treeLogs.receiveShadow = true;
+ treeLeaves.castShadow = true;
+ treeLeaves.receiveShadow = true;
}
function toggleNightMode() {
@@ -761,7 +830,7 @@ function toggleNightMode() {
lights.hemisphere.object.intensity = 0;
lights.directional.object.color.setHex(0xcdddfe); // 0x090254; 0xa8a1fd
scene.background = textures.skyNight.object;
- lights.directional.object.position.set(100, 100, 100); // math the skybox texture moon light
+ lights.directional.object.position.set(100, 100, 100); // match the skybox texture moon light
trainLight.visible = true;
trainLight2.visible = true;
trainLight3.visible = true;
@@ -786,6 +855,13 @@ function createMenu() {
train.visible = !train.visible;
});
gui.add(settings, 'nightMode', false).name('Modo noche').onChange(toggleNightMode);
+ gui.add(settings, 'showHelpers', true).name('Mostrar Guias').onChange(
+ function() {
+ for(let i = 0; i < helpers.length; ++i) {
+ helpers[i].visible = settings.showHelpers;
+ scene.add(helpers[i]);
+ }
+ });
}
function buildScene() {
@@ -806,14 +882,35 @@ function mainLoop() {
orbitControls.enabled = true;
blocker.style.display = 'none';
instructions.style.display = 'none';
+ if(settings.nightMode == true) {
+ trainLight.intensity = 200;
+ trainLight.distance = 100;
+ }
break;
case "firstPersonCamera":
orbitControls.enabled = false;
+ if(settings.nightMode == true) {
+ trainLight.intensity = 200;
+ trainLight.distance = 100;
+ }
+ break;
+ case "trainCamera":
+ case "trainConductorCamera":
+ // por alguna razon cuando la camara es `trainConductorCamera`
+ // la luz principal del tren se ve mas tenue
+ if(settings.nightMode == true) {
+ trainLight.intensity = 1000;
+ trainLight.distance = 1000;
+ }
break;
default:
orbitControls.enabled = false;
blocker.style.display = 'none';
instructions.style.display = 'none';
+ if(settings.nightMode == true) {
+ trainLight.intensity = 200;
+ trainLight.distance = 100;
+ }
break;
}
diff --git a/tp/src/standalone/rails.js b/tp/src/standalone/rails.js
@@ -172,6 +172,8 @@ export function buildRailsFoundation() {
map: textures.durmientes.object
});
const pMesh = new THREE.Mesh(pGeometry, pMaterial);
+ pMesh.receiveShadow = true;
+ pMesh.castShadow = true;
scene.add(pMesh);
}
@@ -245,6 +247,7 @@ function buildRails() {
const railsGeometry = mergeGeometries(railsGeometries);
const rails = new THREE.Mesh(railsGeometry, railsMaterial);
+ rails.castShadow = true;
scene.add(rails);
}
diff --git a/tp/src/train.js b/tp/src/train.js
@@ -149,8 +149,8 @@ function buildChamber() {
}
function buildTrainWheel() {
- const wheel = new THREE.CylinderGeometry(wheelRad, wheelRad, wheelThickness);
- wheel.rotateZ(Math.PI/2);
+ const wheelGeometry = new THREE.CylinderGeometry(wheelRad, wheelRad, wheelThickness);
+ wheelGeometry.rotateZ(Math.PI/2);
const wheelBolt = new THREE.CylinderGeometry(wheelRad, wheelRad, wheelThickness);
wheelBolt.rotateZ(Math.PI/2);
@@ -161,7 +161,10 @@ function buildTrainWheel() {
shininess: 100.0
});
- return new THREE.Mesh(wheel, wheelsMaterial)
+ const wheel = new THREE.Mesh(wheelGeometry, wheelsMaterial);
+ wheel.castShadow = true;
+ wheel.receiveShadow = true;
+ return wheel;
}
function buildTrainAxe(material) {
@@ -194,6 +197,8 @@ export function buildTrain() {
});
const chassis = new THREE.Mesh(chassisGeometry, chassisMaterial);
+ chassis.castShadow = true;
+ chassis.receiveShadow = true;
train.add(chassis);
const chamberGeometry = buildChamber();
@@ -204,11 +209,15 @@ export function buildTrain() {
});
const chamber = new THREE.Mesh(chamberGeometry, chamberMaterial);
+ chamber.castShadow = true;
+ chamber.receive = true;
chassis.add(chamber);
chamber.position.set(0, (chassisHeight + cabinWallThickness)/2, chassisOffset);
const cabinGeometry = buildCabin();
const cabin = new THREE.Mesh(cabinGeometry, chamberMaterial);
+ cabin.castShadow = true;
+ cabin.receive = true;
chassis.add(cabin);
cabin.position.set(0,
(chassisHeight + cabinWallThickness)/2,
@@ -222,6 +231,8 @@ export function buildTrain() {
});
const cabinRoof = new THREE.Mesh(cabinRoofGeometry, roofMaterial);
+ cabinRoof.castShadow = true;
+ cabinRoof.receive = true;
cabin.add(cabinRoof);
cabinRoof.position.set(0, cabinHeight+cabinRoofHeight+cabinWallThickness/2, 0);
@@ -253,7 +264,10 @@ export function buildTrain() {
shininess: 100.0
});
- chassis.add(new THREE.Mesh(cylindersGeometry, cylindersMaterial));
+ const cylinders = new THREE.Mesh(cylindersGeometry, cylindersMaterial)
+ cylinders.castShadow = true;
+ cylinders.receiveShadow = true;
+ chassis.add(cylinders);
chassis.position.set(0,-2,-2.75);
const w1 = buildTrainWheel();