You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
4.4 KiB
JavaScript

import * as THREE from 'three';
import { GLTFLoader } from '../../examples/jsm/loaders/GLTFLoader.js';
import { threejsLessonUtils } from './threejs-lesson-utils.js';
{
const darkColors = {
background: '#333',
};
const lightColors = {
background: '#FFF',
};
const darkMatcher = window.matchMedia( '(prefers-color-scheme: dark)' );
function fogExample( scene, fog, update ) {
scene.fog = fog;
const width = 4;
const height = 3;
const depth = 10;
const geometry = new THREE.BoxGeometry( width, height, depth );
const material = new THREE.MeshPhongMaterial( { color: 'hsl(130,50%,50%)' } );
return {
obj3D: new THREE.Mesh( geometry, material ),
update,
};
}
function houseScene( props, fogInHouse ) {
const { scene, camera } = props;
scene.background = new THREE.Color( '#FFF' );
camera.far = 200;
const loader = new GLTFLoader();
const settings = {
shininess: 0,
roughness: 1,
metalness: 0,
};
loader.load( '/manual/examples/resources/models/simple_house_scene/scene.gltf', ( gltf ) => {
const hackGeometry = new THREE.CircleGeometry( 0.5, 32 );
const box = new THREE.Box3();
const size = new THREE.Vector3();
const center = new THREE.Vector3();
const materials = new Set();
gltf.scene.traverse( ( node ) => {
const material = node.material;
if ( material ) {
// hack in the bottom of the trees since I don't have
// the model file
if ( node.name === 'mesh_11' || node.name === 'mesh_6' ) {
node.updateWorldMatrix( true, false );
box.setFromObject( node );
box.getSize( size );
box.getCenter( center );
const hackMesh = new THREE.Mesh( hackGeometry, node.material );
scene.add( hackMesh );
hackMesh.position.copy( center );
hackMesh.rotation.x = Math.PI * 0.5;
hackMesh.position.y -= size.y / 2;
hackMesh.scale.set( size.x, size.z, 1 );
}
( Array.isArray( material ) ? material : [ material ] ).forEach( ( material ) => {
if ( ! materials.has( material ) ) {
materials.add( material );
for ( const [ key, value ] of Object.entries( settings ) ) {
if ( material[ key ] !== undefined ) {
material[ key ] = value;
}
}
if ( ! fogInHouse && material.name.startsWith( 'fogless' ) ) {
material.fog = false;
}
}
} );
}
} );
scene.add( gltf.scene );
} );
camera.fov = 45;
camera.position.set( 0.4, 1, 1.7 );
camera.lookAt( 1, 1, 0.7 );
const color = 0xFFFFFF;
const near = 1.5;
const far = 5;
scene.fog = new THREE.Fog( color, near, far );
const light = new THREE.PointLight( 0xFFFFFF, 1 );
light.position.copy( camera.position );
light.position.y += 0.2;
scene.add( light );
const target = [ 1, 1, 0.7 ];
return {
trackball: false,
obj3D: new THREE.Object3D(),
update: ( time ) => {
camera.lookAt( target[ 0 ] + Math.sin( time * .25 ) * .5, target[ 1 ], target[ 2 ] );
},
};
}
function createLightDarkFogUpdater( fog ) {
return function () {
const isDarkMode = darkMatcher.matches;
const colors = isDarkMode ? darkColors : lightColors;
fog.color.set( colors.background );
};
}
threejsLessonUtils.addDiagrams( {
fog: {
create( props ) {
const { scene } = props;
const color = 0xFFFFFF;
const near = 12;
const far = 18;
const fog = new THREE.Fog( color, near, far );
return fogExample( scene, fog, createLightDarkFogUpdater( fog ) );
},
},
fogExp2: {
create( props ) {
const { scene } = props;
const color = 0xFFFFFF;
const density = 0.1;
const fog = new THREE.FogExp2( color, density );
return fogExample( scene, fog, createLightDarkFogUpdater( fog ) );
},
},
fogBlueBackgroundRed: {
create( props ) {
const { scene } = props;
scene.background = new THREE.Color( '#F00' );
const color = '#00F';
const near = 12;
const far = 18;
return fogExample( scene, new THREE.Fog( color, near, far ) );
},
},
fogBlueBackgroundBlue: {
create( props ) {
const { scene } = props;
scene.background = new THREE.Color( '#00F' );
const color = '#00F';
const near = 12;
const far = 18;
return fogExample( scene, new THREE.Fog( color, near, far ) );
},
},
fogHouseAll: {
create( props ) {
return houseScene( props, true );
},
},
fogHouseInsideNoFog: {
create( props ) {
return houseScene( props, false );
},
},
} );
}