https://threejs.org/docs/index.html#manual/en/introduction/How-to-use-post-processing
포스트 프로세싱은 렌더링 효과를 추가하는 작업이다.
이는 유티니, 영화에서도 많이 사용하는 기법이기 때문에 이 개념을 한번 숙지하면 여러모로 도움이 될 수 있다.
렌더링 된 화면에 필터효과를 입힐 때 쉐이더를 이용할 수 있지만 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를 사용하면 된다.
댓글