본문 바로가기
FrontEnd/THREE.js

Post Processing

by oncerun 2023. 4. 13.
반응형

https://threejs.org/docs/index.html#manual/en/introduction/How-to-use-post-processing

 

three.js docs

 

threejs.org

포스트 프로세싱은 렌더링 효과를 추가하는 작업이다. 

 

이는 유티니, 영화에서도 많이 사용하는 기법이기 때문에 이 개념을 한번 숙지하면 여러모로 도움이 될 수 있다. 

 

렌더링 된 화면에 필터효과를 입힐 때 쉐이더를 이용할 수 있지만 Three.js에는 다양한 post processor 예제들이 있어 이를 확인하면서 공부할 수 있다. 

 

 

Renderer는 카메라를 통해 Scene의 snapshot을 찍는데, 이를 Render Target이라고 한다.  

 

이때 이를 Canvas에 그리기 전에 우리는 filter를 통해 몇 가지 작업을 추가할 수 있는데 이를 포스트 프로세싱이라고 한다. 

 

인스타앱의 필터도 이러한 후처리 과정을 통해 여러 가지 느낌을 내는 것이다.

 

 

예제를 보면 EffectComposer를 이용한다.

 

import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';

 

 

이를 위해 Renderer를 인자로 받고 effectComposer의 사이즈도 캔버스의 크기에 맞게 조절해주어야 한다. 

 

import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';


//resize 함수에 추가하세요
 effectComposer.setSize(canvasSize.width, canvasSize.height);

현재 어떤 Scene와 어떤 카메라를 사용하는지 등록해주는 RenderPass가 필요합니다. 

 

const renderPass = new RenderPass(scene, camera);
    
effectComposer.addPass(renderPass);

이제 렌더정보를 전달해 주면 됩니다. 

 

렌더기능을 effectCompose에게 위임했기 떄문에 다음 코드는 필요 없다. 

    // renderer.render(scene, camera);
    effectComposer.render();

 

다만 render의 encoding 정보를 따로 설정해주었다면  Render Target을 도중에 가로채기 때문에 지정한 encoding으로 렌더링 되지 않을 수 있다.

 

이를 위해선 다음 객체가 필요하다.

import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';

const shaderPass = new ShaderPass(GammaCorrectionShader);
effectComposer.addPass(shaderPass);

 

이는 빛 효과를 주기 때문에 효과를 주는 파이프라인 어디에 놓을지는 개발자의 판단에 달렸다.

 

 

이제 효과에 대해 알아보자. 

 

1. FilmPass

 

영화 필름의 노이즈한 느낌을 살려주는 효과이다. 뭔가 옛 흑백 티브이 같은 느낌이다.

 

    const filmPass =  new FilmPass(
      0.35,   // noise intensity
      0.025,  // scanline intensity
      648,    // scanline count 0~4096
      true,  // grayscale 색상 보존 정책
    );
    filmPass.renderToScreen = true;
    effectComposer.addPass(filmPass);
    filmPass.uniforms.nIntensity.value = 1;
    filmPass.uniforms.grayscale.value = true;
    filmPass.uniforms.sIntensity.value = 0.9;
    filmPass.uniforms.sCount.value = 1000;

 

 

2. GlitchPass

 

뭔가 오류가 발생해서 자글자글한 느낌이나는 효과를 말한다. 

 

import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';


const glitchPass = new GlitchPass();
effectComposer.addPass(glitchPass);

 

3. AfterimagePass

 

뭔가 잔상이 남는 것처럼 보인다. 

import { AfterimagePass } from 'three/examples/jsm/postprocessing/AfterimagePass.js';


const afterimagePass = new AfterimagePass();
afterimagePass.uniforms.damp.value = 0.9; 
afterimagePass.enabled = true;


effectComposer.addPass(afterimagePass);


//
    const afterimagePass = new AfterimagePass();
    effectComposer.addPass(afterimagePass);


    const shaderPass = new ShaderPass(GammaCorrectionShader);
    effectComposer.addPass(shaderPass);

 

다만 밝아질 수 있는데, 이는 이전 텍스처와 이후 텍스처를 믹스해서 잔상의 느낌을 만들 때 빛을 조절하는 부분이 감마커렉션 쉐이더에 영향을 받기 때문이다. 

 

따라서 체이닝 처럼 생각하여 afterimagePass를 우선적용한 이후 shaderPass를 적용하면 된다.

 

4. HalftonePass

 

질감을 그림처럼 바꿔주는 효과이다. 

 

import { HalftonePass } from 'three/examples/jsm/postprocessing/HalftonePass.js';

 

속성은 다음과 같다.

 

export interface HalftonePassParameters {
    shape?: number;
    radius?: number;
    rotateR?: number;
    rotateB?: number;
    rotateG?: number;
    scatter?: number;
    blending?: number;
    blendingMode?: number;
    greyscale?: boolean;
    disable?: boolean;
}

export class HalftonePass extends Pass {
    constructor(width: number, height: number, params: HalftonePassParameters);
    uniforms: object;
    material: ShaderMaterial;
    fsQuad: FullScreenQuad;
}

 

뭔가 팝아트적인 효과를 낼 수 있다.

 

    const halftonePass = new HalftonePass(
      canvasSize.width,
      canvasSize.height,
      {
        radius: 20, //점 크기
        shape: 1.9, //점 모양 결정 
        scatter: 0.1, //점 사이 간격
        blending: 0.5 , //점 색상 결정
        greyscale: false, //흑백
        disable: false, //점 없애기
      }
    );

 

 

5. UnrealBloomPass

 

빛의 노출값을 조절해서 물체의 밝기를 원하는 데로 조절할 수 있습니다.

import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';



const unrealBloomPass = new UnrealBloomPass(
  new THREE.Vector2(canvasSize.width, canvasSize.height), // 크기
);
unrealBloomPass.strength = 1; // 강도
unrealBloomPass.radius = 0.1; // 반경
unrealBloomPass.threshold = 0.1; // 임계값

effectComposer.addPass(unrealBloomPass);

 

 

* 안티앨리어싱 제거.

  const renderTarget = new THREE.WebGLRenderTarget(
    canvasSize.width,
    canvasSize.height,
    {
      samples: 4,
    }
  );
  const effectComposer = new EffectComposer(renderer, renderTarget);

WebGL 2에서 지원하는 옵션이다.

 

 

 

6. OutlinePass

 

추가한 물체의 외곽선을 추가합니다. 이후 어떤 오브젝트에 적용할지 선택해야 한다.

import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';



const outlinePass = new OutlinePass(
  new THREE.Vector2(canvasSize.width, canvasSize.height),
  scene,
  camera
);
outlinePass.selectedObjects = [...earthGroup.children];
outlinePass.edgeStrength = 20; //선 굵기
outlinePass.edgeGlow = 0.5; //선 반짝임
outlinePass.edgeThickness = 1; //선 두께
outlinePass.pulsePeriod = 1; //선 반짝임 주기
outlinePass.visibleEdgeColor.set('blue'); //선 색상
outlinePass.hiddenEdgeColor.set('#190a05'); //선 색상
effectComposer.addPass(outlinePass);

 

OutlinePass를  적용하니 또 안티엘리어싱이 문제여서. 우선 구의 세그먼츠값을 높였는데, 이러면 연산이 많아저 성능에 문제가 발생한다.

 

이를 다른 방법으로 처리할 수 없을까?

 

7. SMAAPass

 

이는 SMAAPass로 해결이가능하다.

 


import { SMAAPass } from 'three/examples/jsm/postprocessing/SMAAPass.js';

const smaaPass = new SMAAPass(
  canvasSize.width * renderer.getPixelRatio(),
  canvasSize.height * renderer.getPixelRatio()
);
effectComposer.addPass(smaaPass);

 

이러한 템플릿도 괜찮지만 이를 직접 구현할 수도 있다.

 

바로 Shader를 사용하면 된다.

 

 

반응형

'FrontEnd > THREE.js' 카테고리의 다른 글

물리공간 구축  (0) 2023.04.24
3D Computer Graphics (4)  (0) 2023.04.15
Setting  (0) 2023.04.11
추적하기.  (0) 2023.03.22
선형 보간  (0) 2023.03.19

댓글