{"id":3598,"date":"2021-04-20T04:37:18","date_gmt":"2021-04-20T04:37:18","guid":{"rendered":"https:\/\/rengga.dev\/blog\/?p=3598"},"modified":"2023-02-28T04:55:03","modified_gmt":"2023-02-28T04:55:03","slug":"three-js-tutorial-three-js-snowfall","status":"publish","type":"post","link":"https:\/\/rengga.dev\/blog\/three-js-tutorial-three-js-snowfall\/","title":{"rendered":"Three JS Tutorial &#8211; Three JS Snowfall with\u00a0ccapture.js"},"content":{"rendered":"<p><span style=\"color: #ef3207;\"><a style=\"color: #ef3207;\" href=\"https:\/\/rengga.dev\/\" target=\"_blank\" rel=\"noopener\"><strong>Rengga Dev<\/strong><\/a> <\/span>&#8211; Three JS Snowfall with\u00a0ccapture.js<br \/>\n<iframe style=\"width: 100%;\" title=\"Three JS Tutorial - Three JS Snowfall\" src=\"https:\/\/codepen.io\/renggagumilar\/embed\/rNKOMey?default-tab=result&amp;theme-id=dark\" height=\"700\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/renggagumilar\/pen\/rNKOMey\"><br \/>\nThree JS Tutorial &#8211; Three JS Snowfall<\/a> by Rengga Gumilar (<a href=\"https:\/\/codepen.io\/renggagumilar\">@renggagumilar<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\/*\r\nMost of the stuff in here is just bootstrapping. Essentially it's just\r\nsetting ThreeJS up so that it renders a flat surface upon which to draw \r\nthe shader. The only thing to see here really is the uniforms sent to \r\nthe shader. Apart from that all of the magic happens in the HTML view\r\nunder the fragment shader.\r\n*\/\r\n\r\nlet container;\r\nlet camera, scene, renderer;\r\nlet uniforms;\r\n\r\nlet loader=new THREE.TextureLoader();\r\nlet texture;\r\nloader.setCrossOrigin(\"anonymous\");\r\nloader.load(\r\n  'https:\/\/s3-us-west-2.amazonaws.com\/s.cdpn.io\/982762\/noise.png',\r\n  function do_something_with_texture(tex) {\r\n    texture = tex;\r\n    texture.wrapS = THREE.RepeatWrapping;\r\n    texture.wrapT = THREE.RepeatWrapping;\r\n    texture.minFilter = THREE.LinearFilter;\r\n    init();\r\n    animate();\r\n  }\r\n);\r\n\r\nfunction init() {\r\n  container = document.getElementById( 'container' );\r\n\r\n  camera = new THREE.Camera();\r\n  camera.position.z = 1;\r\n\r\n  scene = new THREE.Scene();\r\n\r\n  var geometry = new THREE.PlaneBufferGeometry( 2, 2 );\r\n\r\n  uniforms = {\r\n    u_time: { type: \"f\", value: 1.0 },\r\n    u_resolution: { type: \"v2\", value: new THREE.Vector2() },\r\n    u_noise: { type: \"t\", value: texture },\r\n    u_mouse: { type: \"v2\", value: new THREE.Vector2() }\r\n  };\r\n\r\n  var material = new THREE.ShaderMaterial( {\r\n    uniforms: uniforms,\r\n    vertexShader: document.getElementById( 'vertexShader' ).textContent,\r\n    fragmentShader: document.getElementById( 'fragmentShader' ).textContent\r\n  } );\r\n  material.extensions.derivatives = true;\r\n\r\n  var mesh = new THREE.Mesh( geometry, material );\r\n  scene.add( mesh );\r\n\r\n  renderer = new THREE.WebGLRenderer();\r\n  renderer.setPixelRatio( window.devicePixelRatio );\r\n\r\n  container.appendChild( renderer.domElement );\r\n\r\n  onWindowResize();\r\n  window.addEventListener( 'resize', onWindowResize, false );\r\n\r\n  document.addEventListener('pointermove', (e)=&gt; {\r\n    let ratio = window.innerHeight \/ window.innerWidth;\r\n    uniforms.u_mouse.value.x = (e.pageX - window.innerWidth \/ 2) \/ window.innerWidth \/ ratio;\r\n    uniforms.u_mouse.value.y = (e.pageY - window.innerHeight \/ 2) \/ window.innerHeight * -1;\r\n    \r\n    e.preventDefault();\r\n  });\r\n}\r\n\r\nfunction onWindowResize( event ) {\r\n  renderer.setSize( window.innerWidth, window.innerHeight );\r\n  uniforms.u_resolution.value.x = renderer.domElement.width;\r\n  uniforms.u_resolution.value.y = renderer.domElement.height;\r\n}\r\n\r\nfunction animate(delta) {\r\n  requestAnimationFrame( animate );\r\n  render(delta);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nlet capturer = new CCapture( { \r\n  verbose: true, \r\n  framerate: 60,\r\n  \/\/ motionBlurFrames: 4,\r\n  quality: 90,\r\n  format: 'webm',\r\n  workersPath: 'js\/'\r\n } );\r\nlet capturing = false;\r\n\r\nisCapturing = function(val) {\r\n  if(val === false &amp;&amp; window.capturing === true) {\r\n    capturer.stop();\r\n    capturer.save();\r\n  } else if(val === true &amp;&amp; window.capturing === false) {\r\n    capturer.start();\r\n  }\r\n  capturing = val;\r\n}\r\ntoggleCapture = function() {\r\n  isCapturing(!capturing);\r\n}\r\n\r\nwindow.addEventListener('keyup', function(e) { if(e.keyCode == 68) toggleCapture(); });\r\n\r\nlet then = 0;\r\nfunction render(delta) {\r\n  \r\n  uniforms.u_time.value = -10000 + delta * 0.0005;\r\n  renderer.render( scene, camera );\r\n  \r\n  if(capturing) {\r\n    capturer.capture( renderer.domElement );\r\n  }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rengga Dev &#8211; Three JS Snowfall with\u00a0ccapture.js See the Pen Three JS <a class=\"read-more\" href=\"https:\/\/rengga.dev\/blog\/three-js-tutorial-three-js-snowfall\/\" title=\"Three JS Tutorial &#8211; Three JS Snowfall with\u00a0ccapture.js\" itemprop=\"url\"><\/a><\/p>\n","protected":false},"author":1,"featured_media":3603,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[389,388,264,263,387,384,352,103,227],"newstopic":[],"class_list":{"0":"post-3598","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-javascript","8":"tag-ccapture-js","9":"tag-geometryutils-js","10":"tag-javascript-tutorial","11":"tag-js-tutorial","12":"tag-orbitcontrols-js","13":"tag-three-js","14":"tag-tweenmax-js","15":"tag-web-design","16":"tag-web-designer"},"_links":{"self":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/comments?post=3598"}],"version-history":[{"count":4,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3598\/revisions"}],"predecessor-version":[{"id":3602,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3598\/revisions\/3602"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media\/3603"}],"wp:attachment":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media?parent=3598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/categories?post=3598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/tags?post=3598"},{"taxonomy":"newstopic","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/newstopic?post=3598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}