본문 바로가기
Dev/Computer Graphics

[Nori] Assignment 5: Path Tracing, Microfacet Models, and Multiple Importance Sampling #2

by Jino Park 2019. 7. 4.
반응형

--- 2021/6/25 수정 : 코드 관련 부분 삭제

지난번 포스팅에 이어 Assignment 5를 진행한다. 이번 포스팅에서는 간단한 Path Tracing을 구현한다.

2. path_mats Brute force path tracer (nori)

Path Tracing은 렌더링 방정식을 제안한 Kajiya가 이를 푸는 방법으로 제시한 방법이다. Assignment 4(#1, #2)에서 광원 중 하나를 고르고, 그 위의 점을 sampling하고, 등의 복잡한 과정을 거칠 필요가 없이 단지 렌더링 방정식을 풀기만 하면, 오히려 Assignment 4에서는 볼 수 없던 전역 조명, caustics 등의 현상을 저절로 렌더링할 수 있다.

먼저 PathSimpleIntegrator를 만들기 전에, Emitter 클래스가 해줘야 하는 기능 한 가지가 있다.

L() 함수는 emitter에서 나가는 빛의 radiance를 구해준다. 하지만 area light에선 항상 같으므로, 벡터의 방향만 체크하고 m_radiance를 반환한다.

이제 PathSimpleIntegrator를 구현해보자. 렌더링 방정식 포스팅에서 적었던 내용이지만, 렌더링 방정식의 의미는

한 점에서 나가는 빛의 radiance = 점에서 방출되는 빛의 radiance(emitted) + 점에서 반사되는 빛의 radiance(reflected)

이다. Integrator의 함수 Li(scene, sampler, ray)는 ray가 scene에 부딪힌 점 x에서 ray의 역방향 w로 나가는 빛의 radiance를 구하는 함수이다. 이는 x에서 w로 방출되는 빛의 radiance, x로 들어오는 빛 중에서 w방향으로 반사되는 빛의 radiance를 더하면 된다.

먼저 x에서 w로 방출되는 빛의 radiance를 구해보자. 어떤 경우에 물체에서 빛이 방출될 수 있을까? 물체가 광원인 경우이다. 우리는 이미 Emitter 클래스로 광원을 구현했고, Emitter에서 특정 방향으로 방출되는 빛의 Radiance를 구하는 기능을 위에서 구현했다. 이를 이용하기만 하면 절반은 구현한 셈이다.

Emitter가 아닌 경우에는 방출되는 빛이 없고, Emitter인 경우에는 L()을 이용해 구했다.

이제 x에서 w로 반사되는 빛의 radiance를 구해보자. 즉 방정식의 적분 부분이다. 이런 복잡한 적분식을 푸는 한 가지 방법은 바로 Monte Carlo 적분을 이용하는 것이다. MC 적분의 결론은 아래 그림과 같다.

Monte Carlo 적분의 결론

이를 렌더링 방정식의 적분 부분에 적용시키면,

이다. 하지만 우선 N = 1이라고 생각하고 구현하자. 

주변에서 점 x로 오는 빛을 고려하기 위해 Li()를 재귀적으로 호출하는 것을 알 수 있다. sample을 뽑아, 특정 확률로 재귀 호출을 끝내게 하자.

 이제 위 식을 계산해보자. 하지만 우리가 따로 구현해야 할 것은 별로 없다. 이미 BSDF::sample() 에서 fr() * cos(θ) / (prob of w') 을 계산해주기 때문이다. 우리가 해야할 일은 재귀적으로 이어지는 ray를 만들고 Li()를 호출한 다음, 계산한 항들을 조립하는 것이다.

0.99의 확률로 indirect illumination을 계산하므로, 기댓값을 맞추기 위해 0.99로 나눴다.

전체 path_simple.cpp의 코드는 아래와 같다.

 

링크

나중에 수정이 될 수도 있으니 최신 코드도 참고하기

커밋

Assignment 5

추가 커밋 (이름 변경)

반응형