본문 바로가기
3Js

threejs, 파티클, 마우스 방향 이동

by 영감은어디에 2024. 7. 23.

 

<!DOCTYPE html>
<html>
  <head>
    <meta charset=UTF-8 />
    <style>
        body { margin: 0; overflow: hidden; width: 100vw; height: 100vh; background: radial-gradient(#292929, #000000); }
    canvas{display: block;width: 100%; height: auto; top: 0; left: 0;}
    </style>
  </head>
  <body>
    <canvas id="threebox"></canvas>
    <script type="importmap">
        {
          "imports": {
            "three": "https://cdn.jsdelivr.net/npm/three@0.166.1/build/three.module.js",
            "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.166.1/examples/jsm/"
          }
        }
      </script>
  
    <script type="module">
      import * as THREE from 'three';
      import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
      import { FlakesTexture } from 'three/addons/textures/FlakesTexture.js';
      import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

      let scene, camera, renderer, controls, pointlight, plhelper;

      function init() {
        scene = new THREE.Scene();
        const canvas = document.querySelector('#threebox');


        renderer = new THREE.WebGLRenderer({alpha:true,antialias:true,canvas});
        renderer.setSize(window.innerWidth,window.innerHeight);

        renderer.outputEncoding = THREE.sRGBEncoding;
        renderer.toneMapping = THREE.ACESFilmicToneMapping;
        renderer.toneMappingExposure = 1.25;

        camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,1,1000);
        camera.position.set(0,0,500);
        controls = new OrbitControls(camera, renderer.domElement);

        // controls.autoRotate = true;
        // controls.autoRotateSpeed = 1;
        controls.enableDamping = true;

        pointlight = new THREE.PointLight(0xffffff, 1);
        pointlight.position.set(100,100,100);
        scene.add(pointlight);
        const plhelper = new THREE.PointLightHelper(pointlight, 10);
        const ambientLight = new THREE.AmbientLight(0xffffff, 1)
        scene.add(ambientLight)

        let envmaploader = new THREE.PMREMGenerator(renderer);

        new RGBELoader().setPath('../static/img/').load('rosendal_park_sunset_2k.hdr', function(hdrmap) {

        let envmap = envmaploader.fromCubemap(hdrmap);
        let texture = new THREE.CanvasTexture(new FlakesTexture());
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.x = 10;
        texture.repeat.y = 6;

        const ballMaterial = {
        clearcoat: 0.9,
        clearcoatRoughness:0.1,
        metalness: 0.9,
        roughness:0.5,
        color: 0x8418ca,
        normalMap: texture,
        normalScale: new THREE.Vector2(0.15,0.15),
        envMap: envmap.texture,
        };

        let ballGeo = new THREE.SphereGeometry(100,64,64);
        let ballMat = new THREE.MeshPhysicalMaterial(ballMaterial);
        let ballMesh = new THREE.Mesh(ballGeo,ballMat);
        scene.add(ballMesh);

// 파티클과 마우스 방향 
  let particleContainer = new THREE.Object3D()
  for( var i = 1; i< 200; i++ ){
    var particular = new THREE.Mesh(
      new THREE.CircleGeometry(1.4, 12),
      new THREE.MeshToonMaterial({
        color: 0xffffff,
        side: THREE.DoubleSide
      })
    )
    particular.position.set(mathRandom(300), mathRandom(300), mathRandom(300))
    particular.rotation.set(mathRandom(100), mathRandom(100), mathRandom(100))
    particleContainer.add(particular)
  }
  scene.add(particleContainer)


  // 랜덤 값을 반환하는 함수 정의
  function mathRandom(num = 1) {
    var numValue = -Math.random() * num + Math.random() * num
    return numValue
  }
  let mouse = new THREE.Vector2()
  // 마우스 이벤트 핸들러
  function onMouseMove(event) {
    event.preventDefault()
    // 마우스의 위치 정보를 -1 ~ 1 범위로 변환하여 mouse 벡터에 저장
    mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1
    mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1
  }

  // 마우스 이벤트 리스너 등록
  window.addEventListener('mousemove', onMouseMove, false)

  // 애니메이션 함수
  function animate(currentTime) {
    requestAnimationFrame(animate)
    scene.rotation.y += (mouse.x - camera.rotation.y) * 0.02
    renderer.render(scene, camera)
  }
  //파티클과 마우스방향 끝 


        animate();

        });
      }
      function animate() {
        controls.update();
        renderer.render(scene, camera);
        requestAnimationFrame(animate);
      }
      init();
        // 반응형 처리
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        window.addEventListener('resize', onWindowResize);
    </script>
  </body>
</html>