threejs-fog.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import * as THREE from 'three';
  2. import { GLTFLoader } from '../../examples/jsm/loaders/GLTFLoader.js';
  3. import { threejsLessonUtils } from './threejs-lesson-utils.js';
  4. {
  5. const darkColors = {
  6. background: '#333',
  7. };
  8. const lightColors = {
  9. background: '#FFF',
  10. };
  11. const darkMatcher = window.matchMedia( '(prefers-color-scheme: dark)' );
  12. function fogExample( scene, fog, update ) {
  13. scene.fog = fog;
  14. const width = 4;
  15. const height = 3;
  16. const depth = 10;
  17. const geometry = new THREE.BoxGeometry( width, height, depth );
  18. const material = new THREE.MeshPhongMaterial( { color: 'hsl(130,50%,50%)' } );
  19. return {
  20. obj3D: new THREE.Mesh( geometry, material ),
  21. update,
  22. };
  23. }
  24. function houseScene( props, fogInHouse ) {
  25. const { scene, camera } = props;
  26. scene.background = new THREE.Color( '#FFF' );
  27. camera.far = 200;
  28. const loader = new GLTFLoader();
  29. const settings = {
  30. shininess: 0,
  31. roughness: 1,
  32. metalness: 0,
  33. };
  34. loader.load( '/manual/examples/resources/models/simple_house_scene/scene.gltf', ( gltf ) => {
  35. const hackGeometry = new THREE.CircleGeometry( 0.5, 32 );
  36. const box = new THREE.Box3();
  37. const size = new THREE.Vector3();
  38. const center = new THREE.Vector3();
  39. const materials = new Set();
  40. gltf.scene.traverse( ( node ) => {
  41. const material = node.material;
  42. if ( material ) {
  43. // hack in the bottom of the trees since I don't have
  44. // the model file
  45. if ( node.name === 'mesh_11' || node.name === 'mesh_6' ) {
  46. node.updateWorldMatrix( true, false );
  47. box.setFromObject( node );
  48. box.getSize( size );
  49. box.getCenter( center );
  50. const hackMesh = new THREE.Mesh( hackGeometry, node.material );
  51. scene.add( hackMesh );
  52. hackMesh.position.copy( center );
  53. hackMesh.rotation.x = Math.PI * 0.5;
  54. hackMesh.position.y -= size.y / 2;
  55. hackMesh.scale.set( size.x, size.z, 1 );
  56. }
  57. ( Array.isArray( material ) ? material : [ material ] ).forEach( ( material ) => {
  58. if ( ! materials.has( material ) ) {
  59. materials.add( material );
  60. for ( const [ key, value ] of Object.entries( settings ) ) {
  61. if ( material[ key ] !== undefined ) {
  62. material[ key ] = value;
  63. }
  64. }
  65. if ( ! fogInHouse && material.name.startsWith( 'fogless' ) ) {
  66. material.fog = false;
  67. }
  68. }
  69. } );
  70. }
  71. } );
  72. scene.add( gltf.scene );
  73. } );
  74. camera.fov = 45;
  75. camera.position.set( 0.4, 1, 1.7 );
  76. camera.lookAt( 1, 1, 0.7 );
  77. const color = 0xFFFFFF;
  78. const near = 1.5;
  79. const far = 5;
  80. scene.fog = new THREE.Fog( color, near, far );
  81. const light = new THREE.PointLight( 0xFFFFFF, 1 );
  82. light.position.copy( camera.position );
  83. light.position.y += 0.2;
  84. scene.add( light );
  85. const target = [ 1, 1, 0.7 ];
  86. return {
  87. trackball: false,
  88. obj3D: new THREE.Object3D(),
  89. update: ( time ) => {
  90. camera.lookAt( target[ 0 ] + Math.sin( time * .25 ) * .5, target[ 1 ], target[ 2 ] );
  91. },
  92. };
  93. }
  94. function createLightDarkFogUpdater( fog ) {
  95. return function () {
  96. const isDarkMode = darkMatcher.matches;
  97. const colors = isDarkMode ? darkColors : lightColors;
  98. fog.color.set( colors.background );
  99. };
  100. }
  101. threejsLessonUtils.addDiagrams( {
  102. fog: {
  103. create( props ) {
  104. const { scene } = props;
  105. const color = 0xFFFFFF;
  106. const near = 12;
  107. const far = 18;
  108. const fog = new THREE.Fog( color, near, far );
  109. return fogExample( scene, fog, createLightDarkFogUpdater( fog ) );
  110. },
  111. },
  112. fogExp2: {
  113. create( props ) {
  114. const { scene } = props;
  115. const color = 0xFFFFFF;
  116. const density = 0.1;
  117. const fog = new THREE.FogExp2( color, density );
  118. return fogExample( scene, fog, createLightDarkFogUpdater( fog ) );
  119. },
  120. },
  121. fogBlueBackgroundRed: {
  122. create( props ) {
  123. const { scene } = props;
  124. scene.background = new THREE.Color( '#F00' );
  125. const color = '#00F';
  126. const near = 12;
  127. const far = 18;
  128. return fogExample( scene, new THREE.Fog( color, near, far ) );
  129. },
  130. },
  131. fogBlueBackgroundBlue: {
  132. create( props ) {
  133. const { scene } = props;
  134. scene.background = new THREE.Color( '#00F' );
  135. const color = '#00F';
  136. const near = 12;
  137. const far = 18;
  138. return fogExample( scene, new THREE.Fog( color, near, far ) );
  139. },
  140. },
  141. fogHouseAll: {
  142. create( props ) {
  143. return houseScene( props, true );
  144. },
  145. },
  146. fogHouseInsideNoFog: {
  147. create( props ) {
  148. return houseScene( props, false );
  149. },
  150. },
  151. } );
  152. }