본문 바로가기
컴퓨터 그래픽스/Ray Tracing

Ray Tracing(10) - 슈퍼 샘플링

by SL123 2024. 7. 10.

 

이번 포스팅에서는 슈퍼 샘플링을 통해 이미지의 계단 현상을 
막아보는 방법을 알아보겠습니다.

슈퍼 샘플링의 기본적인 개념은 픽셀 하나에서
Ray를 하나만 쏘는 것이 아니라 여러 개를 쏘는 것입니다.

가운데에서 하나만 쏘는 것이 아니라 왼쪽 위, 오른쪽 위,
왼쪽 아래, 오른쪽 아래를 Ray로 쏴 픽셀의 평균값을 계산합니다.

그렇기 때문에 연산은 많이 하지만 더 부드러운 결과를
얻어올 수 있습니다.

 

슈퍼 샘플링을 하는 여러가지 방법들은 밑에서 확인할 수 있습니다.

https://en.wikipedia.org/wiki/Supersampling

 

Supersampling - Wikipedia

From Wikipedia, the free encyclopedia Spatial anti-aliasing method Calculating the end color value Comparison of a rendered scene without (left side) and with supersampling anti-aliasing applied (right) (Not applying AA is analogous to a nearest-neighbor i

en.wikipedia.org

 

일단 4개의 좌표에서 Ray를 쏘는 방법은 다음과 같습니다.

가로를 dx라고 가정하면 가로의 반은 dx / 2
그 반은 dx / 4라고 보실 수 있습니다.

이런 재귀적인 구조로 픽셀값들을 샘플링한다면
더욱 정확하게 이미지가 그려집니다.

 

픽셀의 World 좌표를 구해온 뒤 재귀적으로 픽셀의 위치를 갱신합니다.
그리고 만약 codition에 재귀가 걸린다면 샘플링된 픽셀값과 눈의 위치를 

이용해 Ray의 위치와 방향을 구해 픽셀에 광선을 비치게 해줍니다.

 

코드로 예시를 들어보겠습니다.

 

함수

RecursionTraceRay2x2

(vec3 eyePos, vec3 pixelWorld, float dx, int RecursionLevel)

가 있다고 가정하겠습니다.

 

 

재귀를 빠져나가는 조건

RecursionLevel이 0이 되는 것입니다.

만약 0이 된다면 eyePos 와 pixelWorld를 이용해 Ray를 구합니다.

(방향과 위치)

 

샘플링 하는 방법

재귀적으로 더 미세한 값을 샘플링해야하기 때문에

float subdx =  dx * 0.5f ; 를 설정합니다.( dx / 2.f 와 같음)

 

subdx 를 이용해 픽셀값을 빼서 왼쪽 아래부터 시작하게 둡니다.

pixelWorld.x = pixelWorld.x - subdx * 0.5f;

pixelWorld.y = pixelWorld.y - subdx * 0.5f;

 

2x2 for 문을 이용해

pixelWorld.x = pixelWorld.x + float(i) * subdx

pixelWorld.y = pixelWorld.y + float(j) * subdx

를 이용해 픽셀값을 조정합니다.

 

이 픽셀값을 더하면서 재귀를 실행합니다.

RecursionTraceRay2x2(eyePos, pixelWorld, dx, RecursionLevel - 1);

재귀가 마무리된다면 2x2 즉, 4이기 때문에 재귀값 * 0.25(평균값)를 합니다.

 

 

이렇게 슈퍼 샘플링을 하는 원리를 대강 알아봤는데요.

만약 VR, 모바일 등 샘플링하는 것이 너무 무겁다 하시면

Blur를 쓰는 것도 방법입니다.

 

다음 포스팅은 반사와 굴절에 대해 알아보겠습니다.

감사합니다.