GLSL를 이용한 그래픽 효과

3차원 그래픽에서 특수 효과는 쉐이더를 통해 대부분 구현됩니다. 이 글은 간단한 GLSL 쉐이더 코드를 통해 물과 불에 대한 효과를 소개합니다.

먼저 불에 대해 구현하고자 하는 모습은 다음과 같습니다.

다음은 물에 대한 결과입니다.

전체 소스코드는 아래 링크를 통해 다운로드 받으실 수 있습니다. 웹기반에서 구현된 코드이므로 js와 css, html 파일로 구성되어 있으며 WebGL 2.0으로 쉐이더 코드가 실행됩니다.

three.js의 scene 구성 요소들 확인하기

3차원에서는 다양한 3차원 객체가 Scene Graph 형태로 구성되어 있습니다. 렌더링하는 결과에 따라 그 형태가 매우 복잡하게 구성될 수 있는데.. Scene Graph의 구성 요소를 확인하기 위한 간단한 함수입니다.

dumpVec3(v3, precision = 3) {
    return `${v3.x.toFixed(precision)}, ${v3.y.toFixed(precision)}, ${v3.z.toFixed(precision)}`;
}

dumpObject(obj, lines = [], isLast = true, prefix = '') {
    const localPrefix = isLast ? '└─' : '├─';
    lines.push(`${prefix}${prefix ? localPrefix : ''}${obj.name || '*no-name*'} [${obj.type}]`);
    const dataPrefix = obj.children.length
        ? (isLast ? '  │ ' : '│ │ ')
        : (isLast ? '    ' : '│   ');
    lines.push(`${prefix}${dataPrefix} pos: ${this.dumpVec3(obj.position)}`);
    lines.push(`${prefix}${dataPrefix} rot: ${this.dumpVec3(obj.rotation)}`);
    lines.push(`${prefix}${dataPrefix} scl: ${this.dumpVec3(obj.scale)}`);
    const newPrefix = prefix + (isLast ? '  ' : '│ ');
    const lastNdx = obj.children.length - 1;
    obj.children.forEach((child, ndx) => {
        const isLast = ndx === lastNdx;
        this.dumpObject(child, lines, isLast, newPrefix);
    });
    return lines;
}

사용은 다음과 같습니다.

console.log(this.dumpObject(root).join('\n'));

결과 예는 다음과 같습니다.

*no-name* [Scene]
  │  pos: 0.000, 0.000, 0.000
  │  rot: 0.000, 0.000, 0.000
  │  scl: 1.000, 1.000, 1.000
  ├─*no-name* [DirectionalLight]
  │    pos: -250.000, 800.000, -850.000
  │    rot: 0.000, 0.000, 0.000
  │    scl: 1.000, 1.000, 1.000
  ├─*no-name* [Object3D]
  │    pos: -550.000, 40.000, -450.000
  │    rot: 0.000, 0.000, 0.000
  │    scl: 1.000, 1.000, 1.000

... 

  ├─*no-name* [Object3D]
  │ │  pos: 571.897, -76.040, -1163.608
  │ │  rot: 0.000, 0.000, 0.000
  │ │  scl: 1.000, 1.000, 1.000
  │ └─CAR_03_3 [Object3D]
  │   │  pos: 0.000, 33.000, 0.000
  │   │  rot: 0.000, 3.142, 0.000
  │   │  scl: 1.500, 1.500, 1.500
  │   └─CAR_03_3_World_ap_0 [Mesh]
  │        pos: 0.000, 0.000, 0.000
  │        rot: 0.000, 0.000, 0.000
  │        scl: 1.000, 1.000, 1.000
  └─*no-name* [Line]
       pos: 0.000, -621.000, 0.000
       rot: 0.000, 0.000, 0.000
       scl: 100.000, 100.000, 100.000