webgl_watch.html 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>three.js webgl - GLTFloader</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <link type="text/css" rel="stylesheet" href="main.css">
  8. </head>
  9. <body>
  10. <div id="container"></div>
  11. <div id="info">
  12. <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - Rolex + aomap - 610 ko
  13. </div>
  14. <!-- Import maps polyfill -->
  15. <!-- Remove this when import maps will be widely supported -->
  16. <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
  17. <script type="importmap">
  18. {
  19. "imports": {
  20. "three": "../build/three.module.js",
  21. "three/addons/": "./jsm/",
  22. "tween": "./jsm/libs/tween.module.js"
  23. }
  24. }
  25. </script>
  26. <script type="module">
  27. import * as THREE from 'three';
  28. import * as TWEEN from 'tween';
  29. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  30. import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
  31. import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
  32. import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
  33. import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
  34. import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
  35. import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
  36. import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
  37. import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
  38. import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
  39. import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';
  40. let composer, camera, scene, renderer;
  41. let gui, dirLight, pointLight, controls, bloomPass, fxaaPass;
  42. let ready = false;
  43. const meshs = {};
  44. const materials = {};
  45. const torad = Math.PI / 180;
  46. const setting = {
  47. roughness:0.09,
  48. metalness:1.0,
  49. opacity:0.4,
  50. threshold: 0,
  51. strength: 0.08,
  52. radius: 0.0,
  53. postProcess:false
  54. }
  55. init();
  56. render();
  57. function init() {
  58. const container = document.getElementById( 'container' );
  59. camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.1, 20 );
  60. camera.position.set( 0.8, 0.5, -1.5 );
  61. scene = new THREE.Scene();
  62. renderer = new THREE.WebGLRenderer( { antialias: true, alpha:false } );
  63. renderer.setPixelRatio( window.devicePixelRatio );
  64. renderer.setSize( window.innerWidth, window.innerHeight );
  65. renderer.toneMapping = THREE.ACESFilmicToneMapping;
  66. renderer.toneMappingExposure = 0.7;
  67. renderer.shadowMap.enabled = true;
  68. renderer.shadowMap.type = THREE.VSMShadowMap;
  69. container.appendChild( renderer.domElement );
  70. new RGBELoader()
  71. .setPath( 'textures/equirectangular/' )
  72. .load( 'lobe.hdr', function ( texture ) {
  73. texture.mapping = THREE.EquirectangularReflectionMapping;
  74. scene.background = texture;
  75. scene.environment = texture;
  76. scene.backgroundBlurriness = 0.5;
  77. scene.backgroundIntensity = 1.0;
  78. scene.environmentIntensity = 1.5;
  79. render();
  80. // model
  81. const loader = new GLTFLoader().setPath( 'models/gltf/' );
  82. loader.setDRACOLoader( new DRACOLoader().setDecoderPath( 'jsm/libs/draco/gltf/' ) );
  83. loader.load( 'rolex.glb', function ( gltf ) {
  84. gltf.scene.rotation.x = Math.PI*0.25
  85. gltf.scene.traverse( ( child ) => {
  86. if ( child.isMesh || child.isGroup ){
  87. if ( child.isMesh ){
  88. child.material.vertexColors = false;
  89. materials[child.material.name] = child.material;
  90. if(child.name!=='glass'){
  91. child.receiveShadow = true;
  92. child.castShadow = true;
  93. }
  94. }
  95. meshs[child.name] = child;
  96. }
  97. })
  98. scene.add( gltf.scene );
  99. meshs.glass.material = new THREE.MeshPhysicalMaterial({
  100. color:0x020205,
  101. transparent:true, opacity:setting.opacity,
  102. metalness:0, roughness:0,
  103. iridescence:0.3,
  104. clearcoat:1.0,
  105. blending:THREE.AdditiveBlending
  106. })
  107. ready = true;
  108. createGUI()
  109. } );
  110. } );
  111. ;
  112. controls = new OrbitControls( camera, renderer.domElement );
  113. controls.minDistance = 0.3;
  114. controls.maxDistance = 10;
  115. controls.target.set( 0, -0.1, 0 );
  116. controls.enableDamping = true;
  117. controls.dampingFactor = 0.05;
  118. controls.update();
  119. dirLight = new THREE.DirectionalLight( 0xFFFFFF, 6 );
  120. dirLight.position.set( -0.1, 0.6, 0.4 );
  121. dirLight.castShadow = true;
  122. scene.add( dirLight );
  123. let shadow = dirLight.shadow;
  124. shadow.mapSize.width = shadow.mapSize.height = 1024;
  125. shadow.radius = 8;
  126. shadow.bias = - 0.0005;
  127. let shadowCam = shadow.camera, s = 0.5;
  128. shadowCam.near = 0.1;
  129. shadowCam.far = 2;
  130. shadowCam.right = shadowCam.top = s;
  131. shadowCam.left = shadowCam.bottom = -s;
  132. // debug shadow
  133. //scene.add( new THREE.CameraHelper(shadowCam) );
  134. pointLight = new THREE.PointLight( 0x7b8cad, 1, 0, 2 );
  135. pointLight.position.set(0.3, -0.2, -0.2);
  136. scene.add( pointLight );
  137. window.addEventListener( 'resize', onWindowResize );
  138. moveCamera();
  139. }
  140. function moveCamera(){
  141. controls.enabled = false;
  142. controls.enableDamping = false;
  143. const sph = new THREE.Spherical();
  144. const target = controls.target;
  145. const tmp = {
  146. distance:controls.getDistance(),
  147. phi:controls.getPolarAngle(),
  148. theta: controls.getAzimuthalAngle()
  149. }
  150. new TWEEN.Tween( tmp )
  151. .to( { distance:1, theta: -Math.PI*0.2 }, 6000 )
  152. .easing( TWEEN.Easing.Quadratic.Out )
  153. .onUpdate( function( n ) {
  154. sph.set( n.distance, n.phi, n.theta );
  155. camera.position.setFromSpherical( sph ).add( target )
  156. camera.lookAt( target )
  157. })
  158. .onComplete( function() {
  159. controls.enabled = true;
  160. controls.enableDamping = true;
  161. })
  162. .start();
  163. }
  164. function postProcess ( b ) {
  165. if(b){
  166. if( composer ) return;
  167. const renderPass = new RenderPass( scene, camera );
  168. const outputPass = new OutputPass();
  169. bloomPass = new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
  170. bloomPass.threshold = setting.threshold;
  171. bloomPass.strength = setting.strength;
  172. bloomPass.radius = setting.radius;
  173. fxaaPass = new ShaderPass( FXAAShader );
  174. const pixelRatio = renderer.getPixelRatio();
  175. fxaaPass.material.uniforms[ 'resolution' ].value.set( 1 / ( window.innerWidth * pixelRatio ), 1 / ( window.innerHeight * pixelRatio ) );
  176. composer = new EffectComposer( renderer );
  177. composer.setPixelRatio( pixelRatio );
  178. composer.addPass( renderPass );
  179. composer.addPass( bloomPass );
  180. composer.addPass( fxaaPass );
  181. composer.addPass( outputPass );
  182. composer.addPass( fxaaPass );
  183. composer.addPass( fxaaPass );
  184. } else {
  185. if(!composer) return;
  186. composer.dispose();
  187. composer = null;
  188. bloomPass = null;
  189. fxaaPass = null;
  190. }
  191. }
  192. function createGUI() {
  193. gui = new GUI();
  194. gui.add( setting, 'roughness', 0, 1, 0.01 ).onChange(upMaterial);
  195. gui.add( setting, 'metalness', 0, 1, 0.01 ).onChange(upMaterial);
  196. gui.add( setting, 'opacity', 0, 1, 0.01 ).onChange(upMaterial);
  197. //
  198. gui.add( setting, 'postProcess' ).onChange(postProcess);
  199. gui.add( setting, 'threshold', 0, 1, 0.01 ).onChange(upBloom);
  200. gui.add( setting, 'strength', 0, 3, 0.01 ).onChange(upBloom);
  201. gui.add( setting, 'radius', 0, 1, 0.01 ).onChange(upBloom);
  202. }
  203. function upMaterial() {
  204. materials.Gold.metalness = materials.Silver.metalness = setting.metalness;
  205. materials.Gold.roughness = materials.Silver.roughness = setting.roughness;
  206. meshs.glass.material.opacity = setting.opacity;
  207. }
  208. function upBloom() {
  209. if( !bloomPass ) return;
  210. bloomPass.threshold = setting.threshold;
  211. bloomPass.strength = setting.strength;
  212. bloomPass.radius = setting.radius;
  213. }
  214. function getTime() {
  215. const currentDate = new Date();
  216. let hour = currentDate.getHours();
  217. let minute = currentDate.getMinutes();
  218. let second = currentDate.getSeconds();
  219. let day = currentDate.getDay();
  220. let mounth = currentDate.getMonth();
  221. let mili = currentDate.getMilliseconds()
  222. if(hour >= 12 ) hour-=12
  223. if(day > 30 ) day=30
  224. meshs.hour.rotation.y = -hour*30 * torad
  225. meshs.minute.rotation.y = -minute * 6 * torad;
  226. meshs.second.rotation.y = -second * 6 * torad;
  227. meshs.mini_03.rotation.y = -day * 12 * torad;
  228. meshs.mini_02.rotation.y = -mounth * 30 * torad;
  229. meshs.mini_01.rotation.y = -mili * 0.36 * torad;
  230. }
  231. function onWindowResize() {
  232. const width = window.innerWidth;
  233. const height = window.innerHeight;
  234. camera.aspect = width / height;
  235. camera.updateProjectionMatrix();
  236. renderer.setSize( width, height );
  237. if( composer ){
  238. composer.setSize( width, height );
  239. if(fxaaPass){
  240. const pr = renderer.getPixelRatio();
  241. fxaaPass.material.uniforms[ 'resolution' ].value.set( 1 / ( width * pr ), 1 / ( height * pr ) );
  242. }
  243. }
  244. }
  245. //
  246. function render() {
  247. requestAnimationFrame( render );
  248. controls.update();
  249. TWEEN.update();
  250. if( composer ) composer.render();
  251. else renderer.render( scene, camera );
  252. if(ready) getTime()
  253. }
  254. </script>
  255. </body>
  256. </html>
粤ICP备19079148号