webgl_materials_envmaps_groundprojected.html 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>
  5. threejs webgl - materials - ground projected environment mapping
  6. </title>
  7. <meta charset="utf-8" />
  8. <meta
  9. name="viewport"
  10. content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
  11. />
  12. <link type="text/css" rel="stylesheet" href="main.css" />
  13. </head>
  14. <body>
  15. <div id="container"></div>
  16. <div id="info">
  17. <a href="https://threejs.org" target="_blank" rel="noopener">threejs</a> -
  18. Ground projected environment mapping. By
  19. <a href="https://twitter.com/CantBeFaraz" target="_blank" rel="noopener"
  20. >Faraz Shaikh</a
  21. >.
  22. <br>
  23. Ferrari 458 Italia model by <a href="https://sketchfab.com/models/57bf6cc56931426e87494f554df1dab6" target="_blank" rel="noopener">vicent091036</a>
  24. </div>
  25. <!-- Import maps polyfill -->
  26. <!-- Remove this when import maps will be widely supported -->
  27. <script
  28. async
  29. src="https://unpkg.com/[email protected]/dist/es-module-shims.js"
  30. ></script>
  31. <script type="importmap">
  32. {
  33. "imports": {
  34. "three": "../build/three.module.js"
  35. }
  36. }
  37. </script>
  38. <script type="module">
  39. import * as THREE from 'three';
  40. import Stats from './jsm/libs/stats.module.js';
  41. import { GUI } from './jsm/libs/lil-gui.module.min.js';
  42. import { OrbitControls } from './jsm/controls/OrbitControls.js';
  43. import { GroundProjectedEnv } from './jsm/objects/GroundProjectedEnv.js';
  44. import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
  45. import { DRACOLoader } from './jsm/loaders/DRACOLoader.js';
  46. const params = {
  47. height: 34,
  48. radius: 440,
  49. toneMappingExposure: 1
  50. };
  51. let camera, scene, renderer, stats, env;
  52. init();
  53. animate();
  54. function init() {
  55. camera = new THREE.PerspectiveCamera(
  56. 45,
  57. window.innerWidth / window.innerHeight,
  58. 1,
  59. 1000
  60. );
  61. camera.position.set( - 16, 8, 16 );
  62. scene = new THREE.Scene();
  63. const cubeLoader = new THREE.CubeTextureLoader();
  64. cubeLoader.setPath( 'textures/cube/lake/' );
  65. const textureCube = cubeLoader.load( [
  66. 'px.png',
  67. 'nx.png',
  68. 'py.png',
  69. 'ny.png',
  70. 'pz.png',
  71. 'nz.png',
  72. ] );
  73. textureCube.encoding = THREE.sRGBEncoding;
  74. env = new GroundProjectedEnv( textureCube );
  75. env.scale.setScalar( 100 );
  76. scene.add( env );
  77. scene.environment = textureCube;
  78. const dracoLoader = new DRACOLoader();
  79. dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );
  80. const loader = new GLTFLoader();
  81. loader.setDRACOLoader( dracoLoader );
  82. const shadow = new THREE.TextureLoader().load(
  83. 'models/gltf/ferrari_ao.png'
  84. );
  85. loader.load( 'models/gltf/ferrari.glb', function ( gltf ) {
  86. const bodyMaterial = new THREE.MeshPhysicalMaterial( {
  87. color: 0xff0000, metalness: 1.0, roughness: 0.5, clearcoat: 1.0, clearcoatRoughness: 0.03, sheen: 0.5
  88. } );
  89. const detailsMaterial = new THREE.MeshStandardMaterial( {
  90. color: 0xffffff, metalness: 1.0, roughness: 0.5
  91. } );
  92. const glassMaterial = new THREE.MeshPhysicalMaterial( {
  93. color: 0xffffff, metalness: 0.25, roughness: 0, transmission: 1.0
  94. } );
  95. const carModel = gltf.scene.children[ 0 ];
  96. carModel.scale.multiplyScalar( 4 );
  97. carModel.rotation.y = Math.PI;
  98. carModel.getObjectByName( 'body' ).material = bodyMaterial;
  99. carModel.getObjectByName( 'rim_fl' ).material = detailsMaterial;
  100. carModel.getObjectByName( 'rim_fr' ).material = detailsMaterial;
  101. carModel.getObjectByName( 'rim_rr' ).material = detailsMaterial;
  102. carModel.getObjectByName( 'rim_rl' ).material = detailsMaterial;
  103. carModel.getObjectByName( 'trim' ).material = detailsMaterial;
  104. carModel.getObjectByName( 'glass' ).material = glassMaterial;
  105. // shadow
  106. const mesh = new THREE.Mesh(
  107. new THREE.PlaneGeometry( 0.655 * 4, 1.3 * 4 ),
  108. new THREE.MeshBasicMaterial( {
  109. map: shadow, blending: THREE.MultiplyBlending, toneMapped: false, transparent: true
  110. } )
  111. );
  112. mesh.rotation.x = - Math.PI / 2;
  113. mesh.renderOrder = 2;
  114. carModel.add( mesh );
  115. scene.add( carModel );
  116. } );
  117. //
  118. renderer = new THREE.WebGLRenderer( { antialias: true } );
  119. renderer.setPixelRatio( window.devicePixelRatio );
  120. renderer.setSize( window.innerWidth, window.innerHeight );
  121. renderer.shadowMap.enabled = true;
  122. renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  123. renderer.outputEncoding = THREE.sRGBEncoding;
  124. //
  125. const controls = new OrbitControls( camera, renderer.domElement );
  126. controls.target.set( 0, 0, 0 );
  127. controls.maxPolarAngle = THREE.MathUtils.degToRad( 80 );
  128. controls.maxDistance = 100;
  129. controls.minDistance = 30;
  130. controls.enablePan = false;
  131. controls.update();
  132. stats = new Stats();
  133. document.body.appendChild( stats.dom );
  134. const gui = new GUI();
  135. gui.add( params, 'height', 20, 50, 0.1 );
  136. gui.add( params, 'radius', 200, 600, 0.1 );
  137. //
  138. document.body.appendChild( renderer.domElement );
  139. window.addEventListener( 'resize', onWindowResize );
  140. }
  141. function onWindowResize() {
  142. camera.aspect = window.innerWidth / window.innerHeight;
  143. camera.updateProjectionMatrix();
  144. renderer.setSize( window.innerWidth, window.innerHeight );
  145. }
  146. function animate() {
  147. requestAnimationFrame( animate );
  148. render();
  149. stats.update();
  150. }
  151. function render() {
  152. renderer.render( scene, camera );
  153. env.radius = params.radius;
  154. env.height = params.height;
  155. }
  156. </script>
  157. </body>
  158. </html>