Three.js - Light

0

WebGL로 가는 길

목록 보기
9/10

Light 클래스

모델 생성

_setupModel() {
  const groundGeometry = new THREE.PlaneGeometry(10, 10);
  const groundMaterial = new THREE.MeshStandardMaterial({
    color: "#2c3e5a",
    roughness: 0.5,
    metalness: 0.5,
    side: THREE.DoubleSide,
  });

  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
  ground.rotation.x = THREE.Math.degToRad(-90);
  this._scene.add(ground);

  const bigSphereGeometry = new THREE.SphereGeometry(1.5, 64, 64, 0, Math.PI);
  const bigSphereMaterial = new THREE.MeshStandardMaterial({
    color: "#fff",
    roughness: 0.1,
    metalness: 0.2,
  });

  const bigSphere = new THREE.Mesh(bigSphereGeometry, bigSphereMaterial);
  bigSphere.rotation.x = THREE.Math.degToRad(-90);
  this._scene.add(bigSphere);

  const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32);
  const torusMaterial = new THREE.MeshStandardMaterial({
    color: "#9b59b6",
    roughness: 0.5,
    metalness: 0.9,
  });

  for (let i = 0; i < 8; i++) {
    const torusPivot = new THREE.Object3D();
    const torus = new THREE.Mesh(torusGeometry, torusMaterial);
    torusPivot.rotation.y = THREE.Math.degToRad(45 * i);
    torus.position.set(3, 0.5, 0);
    torusPivot.add(torus);
    this._scene.add(torusPivot);
  }

  const smallSphereGeometry = new THREE.SphereGeometry(0.3, 32, 32);
  const smallSphereMaterial = new THREE.MeshStandardMaterial({
    color: "#e74c3c",
    roughness: 0.2,
    metalness: 0.5,
  });

  const smallSpherePivot = new THREE.Object3D();
  const smallSphere = new THREE.Mesh(
    smallSphereGeometry,
    smallSphereMaterial
  );
  smallSpherePivot.add(smallSphere);
  smallSpherePivot.name = "smallSpherePivot"; // 이름을 부여해주면 scene 객체를 통해 언제든 조회할 수 있다.
  smallSphere.position.set(3, 0.5, 0);
  this._scene.add(smallSpherePivot);
}

AmbientLight: 주변광(환경광)

단순히 Scene에 존재하는 모든 물체에 대해 단일 색상 광원으로 랜더링되도록 한다.
대부분 밝기 값을 밝기 값을 매우 약하게 지정해서 장면에 추가하여, 광원의 영향을 받지 못하는 물체도 살짝 보여지도록 하는데 사용된다.

  • 인자1: 광원의 색상값
  • 인자2: 광원의 밝기(세기)
new THREE.AmbientLight(0xffffff, 0.2);

HemisphereLight: 주변광

주변광인 것은 AmbientLight와 동일하지만 위, 아래 광원의 색상을 다르게 설정할 수 있다.

  • 인자1: Scene의 위에서 비치는 색상
  • 인자2: Scene의 아래에서 비치는 색상
  • 인자3: 광원의 밝기(세기)
const light = new THREE.HemisphereLight("#b0d8f5", "#bb7a1c", 1);

빛의 방향성을 가지는 광원

DirectionalLight: 태양과 같은 광원

빛과 물체간의 거리에 상관없이 동일한 빛의 효과를 준다.

_setupLight(){
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(0, 5, 0);			// 빛의 위치
  light.target.position.set(0, 0, 0);		// 타겟의 위치
  this._scene.add(light.target);

  // 광원을 시각화해주는 헬퍼 객체
  const helper = new THREE.DirectionalLightHelper(light);
  this._scene.add(helper);
  this._lightHelper = helper;

  this._scene.add(light);
  this._light = light;
}

update(time) {
  time *= 0.001;

  const smallSpherePivot = this._scene.getObjectByName("smallSpherePivot");
  if (smallSpherePivot) {
    smallSpherePivot.rotation.y = THREE.Math.degToRad(time * 50);

    // 업데이트 시 광원이 타겟을 바라보도록 설정
    if (this._light.target) {
      const smallSphere = smallSpherePivot.children[0];
      smallSphere.getWorldPosition(this._light.target.position); 
      //smallSphere의 좌표계의 위치를 구해서 광원의 타겟 위치에 지정한다

      if (this._lightHelper) this._lightHelper.update();
    }
  }
}

PointLight

distance: 이 속성값으로 지정된 거리까지만 광원의 영향을 받도록 함. default: 0 (무한한 거리)

_setupLight() {
  const light = new THREE.PointLight(0xffffff, 2);
  light.position.set(0, 5, 0);
  light.distance = 0;

  const helper = new THREE.PointLightHelper(light);
  this._scene.add(helper);

  this._scene.add(light);
  this._light = light;
}

update(time) {
  time *= 0.001;

  const smallSpherePivot = this._scene.getObjectByName("smallSpherePivot");
  if (smallSpherePivot) {
    smallSpherePivot.rotation.y = THREE.Math.degToRad(time * 50);

    if (this._light) {
      const smallSphere = smallSpherePivot.children[0];
      smallSphere.getWorldPosition(this._light.position); //smallSphere의 좌표계의 위치를 구해서 광원의 타겟 위치에 지정한다

      if (this._lightHelper) this._lightHelper.update();
    }
  }
}

SpotLight

빛이 광원의 위치에서 깔대기 모양으로 퍼져나감

_setupLight() {
  const light = new THREE.SpotLight(0xffffff, 1);
  light.position.set(0, 5, 0); // 광원의 위치
  light.target.position.set(0, 0, 0); // 광원의 타겟 위치
  light.angle = THREE.Math.degToRad(45); // 광원이 만드는 깔대기의 각도
  light.penumbra = 0; // 빛의 감쇄율. default: 0 (빛의 감쇄가 없음)
  this._scene.add(light.target);

  const helper = new THREE.SpotLightHelper(light);
  this._scene.add(helper);
  this._lightHelper = helper;

  this._scene.add(light);
  this._light = light;
}

update(time) {
  time *= 0.001;

  const smallSpherePivot = this._scene.getObjectByName("smallSpherePivot");
  if (smallSpherePivot) {
    smallSpherePivot.rotation.y = THREE.Math.degToRad(time * 50);

    if (this._light.target) {
      const smallSphere = smallSpherePivot.children[0];
      smallSphere.getWorldPosition(this._light.target.position);

      if (this._lightHelper) this._lightHelper.update();
    }
  }
}

RectAreaLight: 형광등이나 창문에서 들어오는 광원

target의 위치를 지정하는게 아니라 각도로 방향을 정해 빛을 비춘다.

  • 인자1: 색상
  • 인자2: 세기
  • 인자3: 광원의 가로길이
  • 인자4: 광원의 세로길이
import {RectAreaLightUniformsLib} from "three/examples/jsm/lights/RectAreaLightUniformsLib";
import {RectAreaLightHelper} from "three/examples/jsm/helpers/RectAreaLightHelper";

_setupLight() {
  RectAreaLightUniformsLib.init(); // 광원을 사용하기 위해 초기화 코드 선행

  const light = new THREE.RectAreaLight(0xffffff, 10, 6, 1);
  // 색상, 세기, 광원의 가로길이, 광원의 세로길이
  light.position.set(0, 5, 0);
  light.rotation.x = THREE.Math.degToRad(-90); // -90도 방향으로 빛을 비춤

  const helper = new RectAreaLightHelper(light);
  light.add(helper);

  this._scene.add(light);
  this._light = light;
}
profile
를 질투하는 그냥 개발자입니다.

0개의 댓글