Angus Emmerson

seung weon, seoΒ·2024λ…„ 12μ›” 17일
0

project

λͺ©λ‘ 보기
9/9
post-thumbnail

πŸ“Ή Angus Emmerson

  • ν”„λ‘œμ νŠΈ 이름: Angus Emmerson
  • μ‚¬μš©ν•œ μ–Έμ–΄: HTML, SCSS, JavaScript
  • μ‚¬μš©ν•œ JavaScript 라이브러리: GSAP, Three.js

Three.js μΊ”λ²„μŠ€ Mesh의 μœ„μΉ˜μ™€ DOM의 μœ„μΉ˜ 동기화 ν•˜κΈ°

Camera μ„€μ •ν•˜κΈ°

const sizes = {
  width: window.innerWidth,
  height: window.innerHeight,
};
...
let camera = null;
setCamera();
...
function setCamera() {
  const distance = 500;
  const fov = (180 * (2 * Math.atan(sizes.height / 2 / distance))) / Math.PI;
  camera = new THREE.PerspectiveCamera(
    fov,
    sizes.width / sizes.height,
    1,
    1000
  );
  camera.position.z = distance;
  scene.add(camera);
}
  1. μž„μ˜μ˜ distance μ„€μ • ν›„ λ³€μˆ˜λ‘œ λ§Œλ“€κΈ° (μœ„ μ˜ˆμ œμ—μ„œλŠ” 500으둜 μ„€μ •)

  2. camera의 fov κ³„μ‚°ν•˜κΈ° (맀우 μ€‘μš”)

    const fov = (180 * (2 * Math.atan(height / 2 / distance))) / Math.PI;
  • λΈŒλΌμš°μ €μ˜ 높이와 Three.js μΊ”λ²„μŠ€ μƒμ—μ„œμ˜ 높이λ₯Ό μΌμΉ˜μ‹œν‚€κΈ° μœ„ν•΄ height 에 window.innerHeight μ‚¬μš© (μœ„ μ˜ˆμ œμ—μ„œλŠ” sizes.height둜 λŒ€μ²΄)
  • μž„μ˜λ‘œ μ„€μ •ν•œ distance κ°’ μ‚¬μš©ν•˜μ—¬ fov κ³„μ‚°ν•˜κΈ°
  1. κ³„μ‚°λœ fovλ₯Ό ν™œμš©ν•˜μ—¬ PerspectiveCamera μƒμ„±ν•˜κΈ°

  2. PerspectiveCamera의 near, farλŠ” 1μ—μ„œ 1000으둜 μ„€μ • (distanceλ₯Ό 500으둜 μ„€μ •ν–ˆκΈ° λ•Œλ¬Έμ— farλ₯Ό 500μ΄ν•˜λ‘œ μ„€μ •ν–ˆμ„κ²½μš° ν™”λ©΄μ—μ„œ 보이지 μ•Šκ²Œ λ©λ‹ˆλ‹€)

  3. μΉ΄λ©”λΌμ˜ zμœ„μΉ˜λ₯Ό distance κ°’μœΌλ‘œ μ„€μ • ν›„ scene에 μΆ”κ°€ν•˜κΈ°

DOM의 μœ„μΉ˜ κ΅¬ν•˜κΈ°

const links = document.querySelectorAll(".link-img");
...
let bounds = {};
...
init();
...
function init() {
  links.forEach((link, i) => {
    mesh = setMesh(i);
    setBounds(link);
  });
}
function setMesh(i) {
  const geometry = new THREE.PlaneGeometry(1, 1, 100, 100);
  const material = new THREE.ShaderMaterial({
  	...
  });
  const plane = new THREE.Mesh(geometry, material);
  scene.add(plane);
  return plane;
}
function setBounds(link) {
  const rect = link.getBoundingClientRect();
  const width = rect.width;
  const height = rect.height;
  const left = rect.left;
  const right = rect.right;
  const x = rect.left + rect.width / 2 - sizes.width / 2;
  const y = -(rect.top + rect.height / 2) + sizes.height / 2;
  bounds = { width, height, left, right, x, y };
  mesh.scale.set(width, height, 1);
  mesh.position.set(x, y, 0);
}
  1. document.querySelectorAll을 μ‚¬μš©ν•˜μ—¬ μœ„μΉ˜λ₯Ό ꡬ할 μš”μ†Œλ“€μ„ μ„ νƒν•˜κ³  λ³€μˆ˜λ‘œ λ§Œλ“€κΈ°

  2. forEach 반볡문 μ‚¬μš©ν•˜κΈ° (λ§€κ°œλ³€μˆ˜λ‘œ 각 μš”μ†Œ, 인덱슀 μ‚¬μš©)

  3. DOM의 μœ„μΉ˜λ₯Ό ꡬ할 setBounds ν•¨μˆ˜ λ§Œλ“€κΈ° (각 μš”μ†Œλ“€, 즉 linkλ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›μŒ)

  4. getBoundingClientRect()λ₯Ό μ‚¬μš©ν•˜μ—¬ 각 μš”μ†Œμ˜ 크기 및 μœ„μΉ˜ 정보 λ³€μˆ˜ rect에 μ €μž₯ν•˜κΈ°

  5. width, height, left, right, x, y 값을 각각 λ³€μˆ˜λ‘œ λ§Œλ“€κΈ°

    • x, y 값은 각 μš”μ†Œμ˜ 쀑심 μœ„μΉ˜ κ°’ (Mesh의 μœ„μΉ˜ μ„€μ •ν• λ•Œμ— μ‚¬μš©ν•  κ°’)
      x : 쒌츑 μœ„μΉ˜ + λ„ˆλΉ„ / 2 - μœˆλ„μš° λ„ˆλΉ„ / 2
      y : μœˆλ„μš° 높이 / 2 - (μœ„μͺ½ μœ„μΉ˜ + 높이 / 2)
  6. 객체 bounds에 μœ„μ—μ„œ ꡬ해진 κ°’λ“€ μ €μž₯ν•˜κΈ°

  7. 미리 λ§Œλ“€μ–΄ 놓은 mesh의 scale 값을 μš”μ†Œμ˜ λ„ˆλΉ„, 높이 κ°’μœΌλ‘œ μ„€μ •ν•˜κΈ° (z 값은 1둜 μ„€μ •)

  8. bounds의 x, y 값을 ν™œμš©ν•˜μ—¬ mesh의 position μ„€μ •ν•˜κΈ° (z 값은 0으둜 μ„€μ •)

Shaderλ₯Ό ν™œμš©ν•˜μ—¬ μŠ€ν¬λ‘€μ‹œ λ¬Όκ²° 효과 κ΅¬ν˜„ν•˜κΈ°

슀크둀 이벀트 μΆ”κ°€ν•˜κΈ°

const state = {
  scroll: {
    target: 0,
    current: 0,
  },
  ...
};
...
window.addEventListener("wheel", (e) => {
  handleWheel(e);
});
...
function handleWheel(e) {
  let delta = e.deltaY;
  delta *= 0.55;
  handleScroll(delta);
}
function handleScroll(delta) {
  state.scroll.target = Math.round(state.scroll.target + delta * 0.6);
  state.scroll.target = THREE.MathUtils.clamp(
    state.scroll.target,
    0,
    sizes.width
  );
}
  1. 슀크둀 및 기타 μƒνƒœλ₯Ό 관리할 객체 state λ§Œλ“€κΈ°

  2. 휠 μ΄λ²€νŠΈμ— μ‚¬μš©ν•  ν•¨μˆ˜ handleWheel λ§Œλ“€κΈ° (λ§€κ°œλ³€μˆ˜λ‘œ 이벀트 e 보내기)

  3. λ³€μˆ˜ delta에 e.deltaY κ°’ μ •μ˜ν•˜κΈ°

e.deltaYλž€?

마우슀 휠의 수직 μ΄λ™λŸ‰μ„ μ˜λ―Έν•˜λ©°, μ•„λž˜λ‘œ 슀크둀 ν–ˆμ„λ•ŒλŠ” μ–‘μˆ˜ κ°’, μœ„λ‘œ 슀크둀 ν–ˆμ„λ•ŒλŠ” 음수 값을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

  1. delta에 0.55λ₯Ό κ³±ν•˜μ—¬ μ΄λ™λŸ‰μ„ μ‘°μ •ν•˜κΈ°

  2. deltaλ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ ν•˜λŠ” handleScroll ν•¨μˆ˜ λ§Œλ“€κ³ , ν˜ΈμΆœν•˜κΈ°

  3. delta에 0.6을 κ³±ν•˜μ—¬ μ΄λ™λŸ‰μ„ ν•œλ²ˆ 더 μ‘°μ •ν•œ ν›„ state의 슀크둀 νƒ€κ²Ÿμ„ λ”ν•œ 값을 Math.round()λ₯Ό μ‚¬μš©ν•˜μ—¬ 반올림 ν•œ ν›„, κ·Έ 값을 ν• λ‹Ήν•˜κΈ°

  4. Three.js의 λ‚΄μž₯ ν•¨μˆ˜ MathUtils.clampλ₯Ό μ‚¬μš©ν•˜μ—¬ state의 슀크둀 νƒ€κ²Ÿ 값을 0λΆ€ν„° sizes.width 즉, μœˆλ„μš° λ„ˆλΉ„λ₯Ό λ„˜μ§€ μ•Šλ„λ‘ κ³ μ •μ‹œν‚€κΈ° (μœˆλ„μš° λ„ˆλΉ„λŠ” μœ„ 예제λ₯Ό μœ„ν•΄ μž„μ˜λ‘œ μ„€μ •ν•œ κ°’)

clampλž€?

THREE.MathUtils.clamp(value, min, max);
// 숫자 값을 νŠΉμ • λ²”μœ„ λ‚΄λ‘œ μ œν•œν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€. 즉, 값이 μ§€μ •λœ μ΅œμ†Œκ°’κ³Ό μ΅œλŒ€κ°’ 사이에 μžˆλ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.

λ Œλ”λ§μ— μ‚¬μš©ν•  κ°’ μ—…λ°μ΄νŠΈ ν•˜κΈ°

const uniforms = {
  uResolution: { value: new THREE.Vector2(sizes.width, sizes.height) },
  uProgress: { value: 0 },
  uEffectWidth: { value: 0.75 },
  uStrength: { value: 0 },
};
const state = {
  ...
  ,
  progress: {
    target: 0,
    current: -0.5,
  },
  strength: {
    target: 0,
    current: 0,
    base: -0.8,
  },
};
const clock = new THREE.Clock();
let deltaTime = null;
...
function update() {
  deltaTime = clock.getDelta() * 1000;
  const progress = THREE.MathUtils.mapLinear(
    state.scroll.target,
    0,
    sizes.width,
    0,
    1
  );
  state.progress.target = progress - 0.5;
  state.progress.current = lerp(
    state.progress.current,
    state.progress.target,
    0.09
  );
  if (Math.abs(state.progress.current - state.progress.target) < 0.02) {
    state.strength.target = 0;
  } else {
    state.strength.target = state.strength.base;
  }
  state.strength.current = lerp(
    state.strength.current,
    state.strength.target,
    0.04
  );
  uniforms.uProgress.value = state.progress.current;
  uniforms.uStrength.value = state.strength.current;
  ...
}
function lerp(value, target, time) {
  return value + (target - value) * (time / (16.6666666666667 / deltaTime));
}
  1. Shaderμ—μ„œ μ‚¬μš©ν•  값듀을 담은 객체 uniforms λ§Œλ“€κΈ°

    const uniforms = {
    	uResolution: { value: new THREE.Vector2(sizes.width, sizes.height) },
        // Three.js의 Vector2λ₯Ό ν™œμš©ν•˜μ—¬, ν˜„μž¬ ν™”λ©΄μ˜ 해상도 λ‹΄κΈ°
    	uProgress: { value: 0 },
        // 슀크둀의 진행도λ₯Ό λ‚˜νƒ€λ‚΄λŠ” κ°’
    	uEffectWidth: { value: 0.75 },
        // λ¬Όκ²° 효과의 λ„ˆλΉ„λ₯Ό μ •ν•˜λŠ” κ°’
    	uStrength: { value: 0 },
        // 슀크둀 ν•˜μ˜€μ„ λ•Œ, λ¬Όκ²° 효과의 강도λ₯Ό μ •ν•˜λŠ” κ°’
    };
  2. μƒνƒœ 관리 객체 state에 progress, strength ν•­λͺ© μΆ”κ°€ν•˜κΈ°

  3. Three.js의 Clock을 μ‚¬μš©ν•˜μ—¬ ν”„λ ˆμž„ κ°„ μ‹œκ°„ κ²½κ³Όλ₯Ό μΈ‘μ •ν•˜κΈ°

  4. ν˜„μž¬μ˜ ν”„λ ˆμž„ 레이트λ₯Ό 담을 λ³€μˆ˜ deltaTime λ§Œλ“€κΈ°

  5. λ Œλ”λ§μ— μ‚¬μš©ν•  값듀을 μ‹€μ‹œκ°„μœΌλ‘œ μ—…λ°μ΄νŠΈ ν•  ν•¨μˆ˜ update() λ§Œλ“€κΈ°

  6. Clock의 getDelta()λ₯Ό μ‚¬μš©ν•˜μ—¬ ν˜„μž¬μ˜ ν”„λ ˆμž„ 레이트λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ μ—…λ°μ΄νŠΈ ν•˜κΈ°

  7. ν˜„μž¬μ˜ 슀크둀 진행도λ₯Ό 0λΆ€ν„° 1κΉŒμ§€μ˜ κ°’μœΌλ‘œ λ°”κΎΈκΈ° μœ„ν•΄ Three.js의 λ‚΄μž₯ ν•¨μˆ˜ MathUtils.mapLinearλ₯Ό μ‚¬μš©ν•˜κΈ°

mapLinearλž€?

THREE.MathUtils.mapLinear(x, a1, a2, b1, b2);
// x: λ³€ν™˜ν•  μž…λ ₯ κ°’
// a1: μž…λ ₯ κ°’μ˜ μ΅œμ†Œκ°’
// a2: μž…λ ₯ κ°’μ˜ μ΅œλŒ€κ°’
// b1: 좜λ ₯ κ°’μ˜ μ΅œμ†Œκ°’
// b2: 좜λ ₯ κ°’μ˜ μ΅œλŒ€κ°’
// 주어진 μž…λ ₯ λ²”μœ„μ—μ„œ ν•΄λ‹Ή 값이 μ°¨μ§€ν•˜λŠ” λΉ„μœ¨μ„ κΈ°μ€€μœΌλ‘œ μƒˆλ‘œμš΄ 좜λ ₯ λ²”μœ„μ˜ 값을 κ³„μ‚°ν•©λ‹ˆλ‹€.
  1. λ§΅ν•‘λœ 값을 담은 λ³€μˆ˜ progress에 -0.5 만큼 λΊ€ 값을 state의 progress νƒ€κ²Ÿ κ°’μœΌλ‘œ μ„€μ • (0을 쀑간 κ°’μœΌλ‘œ λ§Œλ“€κΈ° μœ„ν•΄μ„œ)

  2. ν•¨μˆ˜ lerpλ₯Ό μ‚¬μš©ν•˜μ—¬ state의 progress ν˜„μž¬ 값을 νƒ€κ²Ÿ κ°’μœΌλ‘œ λΆ€λ“œλŸ½κ²Œ λ³΄κ°„ν•˜κΈ°

lerpλž€?

function lerp(value, target, time) {
  return value + (target - value) * (time / (16.6666666666667 / deltaTime));
}
// 60ν”„λ ˆμž„(μ•½ 16.67ms)을 deltaTime으둜 λ‚˜λˆ”μœΌλ‘œμ¨, κ°’μ˜ λ³€ν™” 속도λ₯Ό μΌμ •ν•˜κ²Œ μœ μ§€
// lerp ν•¨μˆ˜λŠ” μ„ ν˜• 보간(Linear Interpolation)을 κ΅¬ν˜„ν•œ ν•¨μˆ˜λ‘œ, 두 κ°’ 사이λ₯Ό λΆ€λ“œλŸ½κ²Œ λ³€ν™”μ‹œν‚¬λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
  1. progress의 ν˜„μž¬ 값을 νƒ€κ²Ÿ κ°’μœΌλ‘œ λΊ€ 값을 Math.absλ₯Ό μ‚¬μš©ν•˜μ—¬ μ ˆλŒ€ κ°’μœΌλ‘œ λ§Œλ“€κ³ , 이 값이 0.02보닀 μž‘μ„λ•ŒλŠ” strength의 νƒ€κ²Ÿ 값을 0으둜, 클 μ‹œμ—λŠ” strength의 κΈ°λ³Έ 값인 -0.8둜 μ„€μ • (슀크둀 ν•˜μ§€ μ•Šμ„ μ‹œμ—λŠ” λ¬Όκ²° 효과λ₯Ό 주지 μ•ŠκΈ° μœ„ν•΄μ„œ)

  2. uniform의 uProgress 값은 progress의 ν˜„μž¬ κ°’μœΌλ‘œ, uStrength 값은 strength의 ν˜„μž¬ κ°’μœΌλ‘œ μ„€μ •ν•˜κΈ°

vertexShader μ½”λ“œ μž‘μ„±ν•˜κΈ°

function setMesh(i) {
  ...
  const material = new THREE.ShaderMaterial({
    uniforms: {
      uTexture: new THREE.Uniform(textures[i]),
      uResolution: uniforms.uResolution,
      uEffectWidth: uniforms.uEffectWidth,
      uProgress: uniforms.uProgress,
      uStrength: uniforms.uStrength,
    },
    vertexShader: 
    `
      uniform float uProgress;
      uniform float uEffectWidth;
      uniform float uStrength;
      uniform vec2 uResolution;
      varying vec2 vUv; 
      void main(){
        vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
        float normalizedX = modelViewPosition.x / uResolution.x;
        normalizedX = (normalizedX - uProgress) / (uEffectWidth * 1.2);
        float mappedVar = normalizedX * 2.0;
        float wave = abs(normalizedX - mappedVar);
        wave = smoothstep(0.0, 0.5, wave);
        wave = 1.0 - wave;
        modelViewPosition.z += wave * uStrength * 100.0;
        gl_Position = projectionMatrix * modelViewPosition;
        vUv = uv;
      }
    `,
    ...
    ,
  });
  ...
}
  1. ShaderMaterial에 각 uniform μš”μ†Œλ“€ μΆ”κ°€ν•˜κΈ°
    uniforms: {
          uTexture: new THREE.Uniform(textures[i]),
          // TextureLoaderλ₯Ό μ‚¬μš©ν•˜μ—¬ 뢈러온 ν…μŠ€μ³ μ €μž₯
          uResolution: uniforms.uResolution,
          // ν˜„μž¬ ν™”λ©΄μ˜ 해상도
          uEffectWidth: uniforms.uEffectWidth,
          // λ¬Όκ²° 효과의 λ„ˆλΉ„
          uProgress: uniforms.uProgress,
          // 슀크둀 진행도
          uStrength: uniforms.uStrength,
          // λ¬Όκ²° 효과의 강도
        },
  2. vertexShader μ—μ„œ μ €μž₯ν•΄ λ‘” 각 uniform κ°’ 뢈러였기

glsl의 데이터 νƒ€μž…

float: 3.14, 0.5
// λΆ€λ™μ†Œμˆ˜μ  숫자
int: 1, -10
// μ •μˆ˜
bool: true, false
// 논리값, λΆˆλ¦¬μ–Έ
vec2: vec2(0.5, 1.0)
// 2차원 벑터
vec3: vec3(1.0, 0.0, 0.0)
// 3차원 벑터
vec4: vec4(1.0, 0.0, 0.0, 1.0)
// 4차원 벑터
mat2, mat3, mat4: mat4(1.0)
// ν–‰λ ¬ 데이터 νƒ€μž…
sampler2D: texture(sampler, uv)
// 2D ν…μŠ€μ²˜ μƒ˜ν”Œλ§ (주둜 ν…μŠ€μ³ 뢈러올 λ•Œμ— μ‚¬μš©)
  1. λͺ¨λΈ μ’Œν‘œλ₯Ό 카메라 κΈ°μ€€ μ’Œν‘œλ‘œ λ³€ν™˜ν•œ 값인 modelViewMatrix에 ν˜„μž¬ ν”Œλ ˆμΈμ˜ μ’Œν‘œ 값인 position을 κ³±ν•˜μ—¬ vec4 λ³€μˆ˜ modelViewPosition λ§Œλ“€κΈ° (카메라 κΈ°μ€€ μ’Œν‘œλ‘œ μž‘μ—…ν•˜μ—¬ λ¬Όκ²° 효과λ₯Ό 일관성 있게 μ μš©μ‹œν‚€κΈ° μœ„ν•΄μ„œ)

  2. modelViewPosition의 x값을 ν˜„μž¬ 해상도인 uResolution.x으둜 λ‚˜λˆˆ ν›„ float λ³€μˆ˜ normalizedX에 μ €μž₯ (해상도에 λ”°λ₯Έ μ •κ·œν™” κ°’, 값을 0μ—μ„œ 1 λ²”μœ„λ‘œ λ³€ν™˜ν•˜κΈ° μœ„ν•΄μ„œ)

  3. 슀크둀의 진행도 (uProgress)와, 물결효과의 λ„ˆλΉ„ (uEffectWidth)에 따라 normalizedX κ°’ μ‘°μ •ν•˜κΈ°

    normalizedX = 
      (normalizedX - uProgress) // 슀크둀 ν•  λ•Œ λ¬Όκ²° 효과의 λ°©ν–₯ μ„€μ • (μ™Όμͺ½μ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ)
      / 
      (uEffectWidth * 1.2); // λ¬Όκ²° 효과의 λ„ˆλΉ„μ— μž„μ˜μ˜ κ°’ κ³±ν•˜κΈ° (μœ„ μ˜ˆμ œμ—μ„œλŠ” 1.2 μ‚¬μš©)
  4. μ‘°μ •λœ normalizedX 값에 2.0을 κ³±ν•˜μ—¬ float λ³€μˆ˜ mappedVar λ§Œλ“€κΈ° (μœ„ μ˜ˆμ œμ—μ„œλŠ” 2.0 μ‚¬μš©)

  5. normalizedXμ—μ„œ mappedVar의 차이 값을 abs ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ ˆλŒ€κ°’μœΌλ‘œ λ§Œλ“€κ³  float λ³€μˆ˜ wave에 μ €μž₯ (두 κ°’μ˜ 차이λ₯Ό λ¬Όκ²° νš¨κ³Όμ— μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ)

  6. smoothstep ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ¬Όκ²° 효과λ₯Ό λΆ€λ“œλŸ½κ²Œ λ§Œλ“€κΈ° (0.0λΆ€ν„° 0.5 μ‚¬μ΄μ˜ 값을 κ²½κ³„κ°’μœΌλ‘œ μ‚¬μš©)

smoothstep ν•¨μˆ˜λž€?

float smoothstep(float edge0, float edge1, float x);
// edge0: 보간이 μ‹œμž‘λ˜λŠ” κ°’ (μ΅œμ†Œ 경계값)
// edge1: 보간이 λλ‚˜λŠ” κ°’ (μ΅œλŒ€ 경계값)
// x: 보간 λŒ€μƒ κ°’
// 두 경계값 μ‚¬μ΄μ—μ„œ λ§€λ„λŸ½κ²Œ 보간(smooth interpolation)을 μˆ˜ν–‰ν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.
  1. wave κ°’ λ°˜μ „μ‹œν‚€κΈ°

    wave = 1.0 - wave;
    // λ¬Όκ²° 효과λ₯Ό 쀑심 λΆ€λΆ„μ—μ„œ κ°€μž₯ κ°•ν•˜κ²Œ λ§Œλ“€κΈ° μœ„ν•΄μ„œ
  2. modelViewPosition의 zκ°’ μ‘°μ •ν•˜κΈ°

    modelViewPosition.z += wave * uStrength * 100.0;
    // λ³€μˆ˜ wave에 λ¬Όκ²° 효과의 강도(uStrength)와 μž„μ˜μ˜ κ°’(100.0)을 κ³±ν•œ 후에 modelViewPosition의 z μœ„μΉ˜μ— λ”ν•˜κΈ°
  3. projectionMatrixλ₯Ό μ‘°μ •λœ modelViewPosition에 κ³±ν•˜μ—¬ μ΅œμ’… μœ„μΉ˜ (gl_Position) μ„€μ •

  4. uvμ’Œν‘œλ₯Ό fragmentShaderμ—μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄, varying λ³€μˆ˜ vUv λ§Œλ“€κΈ° (uv μ’Œν‘œλŠ” attribute 속성이기 λ•Œλ¬Έμ— fragmentShaderμ—μ„œ μ‚¬μš© λΆˆκ°€)

fragmentShader μ½”λ“œ μž‘μ„±ν•˜κΈ°

const material = new THREE.ShaderMaterial({
  uniforms: {
    uTexture: new THREE.Uniform(textures[i]),
    ..,
  }
  ,
  fragmentShader: 
  `
    uniform sampler2D uTexture;
    varying vec2 vUv;
    void main(){
      vec4 tex = texture2D(uTexture, vUv);
      gl_FragColor = vec4(tex.rgb, 1.0);
    }
  `
});
  1. sampler2Dλ₯Ό μ‚¬μš©ν•˜μ—¬ 각 ν…μŠ€μ³(uTexture) 뢈러였기

  2. vertexShaderμ—μ„œ μ €μž₯ν•œ vUv κ°’ (varying) 뢈러였기

  3. texture2D둜 ν…μŠ€μ³ 및 uv 값을 λ³€ν™˜ν•˜μ—¬ vec4 λ³€μˆ˜ tex에 μ €μž₯ν•˜κΈ°

  4. λ³€μˆ˜ tex의 rgb을 ν™œμš©ν•˜μ—¬ ν”Œλ ˆμΈμ˜ μ΅œμ’… 색상 μ„€μ • (1.0은 ν”Œλ ˆμΈμ˜ 투λͺ…도 alpha κ°’)
    * rgbλŠ” xyz와 κ°™μŠ΅λ‹ˆλ‹€. (색상이기 λ•Œλ¬Έμ— rgb둜 μ‚¬μš©)

profile
to reach new possibilities

0개의 λŒ“κΈ€