THREE.PointLight의 decay 속성

이 속성은 거리에 따른 광원의 감쇄 지수값입니다. 먼저 수식을 보면..

광원이 거리에 따라 얼마나 빨리 빛을 잃어버리는지를 결정하는 값인데요. 위 식에서 I는 거리에 따라 결정되는 실제 밝기값이고 I_0는 광원을 생성할때 지정한 밝기값이며, distance는 광원에서 물체까지의 거리입니다. decay는 우리가 살펴보고 있는 감쇠 계수입니다.

decay의 값은 2가 기본값입니다. 즉, 2이면 일반적인 감쇠인데 빛은 거리의 제곱에 따라 감쇄됩니다. 만약 decay 값을 1로 변경하면 거리에 반비례하게되고 0이면 거리와는 상관없이 일정한 밝기를 유지하게 됩니다.

PointLight에는 distance라는 속성도 있는데 이는 광원이 영향을 주는 최대 범위입니다. decay는 이 범위 안에서 거리에 따른 밝기 세기에 대한 감속 속도를 결정합니다. 이 decay를 조절하여 현실적인 조명 효과를 만들거나(2), 특수한 조명을 연출할 수도 있습니다.

R3F에서 lint 에러 제거하기

아래처럼 빨간펜 선생님의 지적이 눈에 거슬린다면 …

먼저 위의 코드 중 하나는 다음처럼…

extend(THREE as any);

그리고 src/@types 폴더를 만들고 원하는 이름의 확장자가 *.d.ts 인 파일(나의 경우 three.webgpu.d.ts)을 만들어 다음처럼 내용을 채웁니다.

import * as THREE from 'three/webgpu';
import { ReactThreeFiber } from '@react-three/fiber';

declare module '@react-three/fiber' {
  interface ThreeElements {
    meshBasicNodeMaterial: ReactThreeFiber.Object3DNode;
  }
}

그럼 더 이상 빨간펜 선생님의 잔소리는 사요나라… 입니다. 물론 필요할 경우 지적당한 타입을 *.d.ts에 계속 추가해야 합니다.

WebGPU 방식의 포인트 렌더링

WebGL은 결국 WebGPU로 대체될 기술이기에 그간 개발된 프로젝트를 WebGPU 기반으로 변경하고 있습니다. 다행히 많은 코드가 WebGL과 WebGPU에서도 동일하게 작동하기는 하지만 제대로 작동하지 않는 코드도 상당합니다. 특히 재질과 관련된 부분이 문제고 이는 재질이 쉐이더와 직접적으로 연결되어 있기 때문입니다. WebGL과 WebGPU에서 사용하는 쉐이더는 그 언어부터가 다른데 각각 GLSL과 WGSL입니다. 이 글은 WebGL에서는 정상적으로 작동하던 포인트 레더링 코드가 WebGPU에서는 더 이상 정상적으로 작동하지 않는 부분에 대한 정리입니다. 바로 포인트의 크기에 대한 부분인데요. WebGPU에서 포인트에 대한 렌더링 코드는 다음과 같습니다.

private setupModel() {
  const count = 10000;
  const positions = new Float32Array(count * 3);
  for (let i = 0; i < count; i++) {
    positions[i * 3 + 0] = THREE.MathUtils.randFloatSpread(5);
    positions[i * 3 + 1] = THREE.MathUtils.randFloatSpread(5);
    positions[i * 3 + 2] = THREE.MathUtils.randFloatSpread(5);
  }
  const positionAttribute = new THREE.InstancedBufferAttribute(positions, 3);

  const material = new THREE.PointsNodeMaterial({
    color: 0xffff00,
    positionNode: instancedBufferAttribute(positionAttribute),
    sizeNode: float(.1),
    sizeAttenuation: true,

    alphaTestNode: float(1).sub(shapeCircle()),
  });

  const points = new THREE.Sprite(material);
  points.count = count;
  this.scene.add(points);
}

이 코드는 10000개의 포인트를 렌더링하는 것으로 WebGL에서는 THREE.Points 였던 것이 WebGPU에서는 THREE.Sprite로.. THREE.PointsMaterial 였던 것이 THREE.PointsNodeMaterial로.. 그밖에 포인트들의 위치를 정의하는 부분의 코드 역시도 변경되었습니다. WebGPU 기반에서는 상당 부분을 TSL이라는 개념이 적용되는데 THREE.PointsNodeMaterial을 생성할때 positionNode와 sizeNode 그리고 사각형 모양의 포인트가 아닌 원 모양의 포인트를 만들기 위한 alphaTestNode에서 TSL가 사용되고 있습니다.

WebGPU는 WebGL을 대체하는 기술이고 보다 효율적이고 보다 빠릅니다. 이미 모바일에서도 문제없이 잘작동하고 있구요. 만약 three.js로 새로운 3D 프로젝트를 기획하고 있다면 WebGPU로 방향을 잡아 진행하는 것을 추천합니다.