이제 우리는 vertex shader로부터 rasterizer 까지 살펴 보았다. 하나의 삼각형 안에 들어가는 모든 fragment를 계산했다는 것이고, 그 fragment에는 선형보간을 통해 얻어진 normal과 texture coordinate가 저장이 되어있을 것이다. 그 다음 단계는 fragment shader이고 각 fragment의 색상을 결정한다. fragment shader는 texturing과 lighting을 진행한다.

이번 포스팅에서는 texturing을 알아보도록 하자.


Texture Coordinates

texture는 모델링한 polygon mesh에 입히는 옷이다. 다음과 같은 원통에 texturing을 진행한다고 해보자.

image texturing

이미지와 mesh가 주어졌을 때 mesh 표면에다가 texture를 입히는 것이다.

texture는 texel 이라는 elements로 이루어져 있다. 이전에 계산된 fragment에는 해당 점들에 대응하는 texture 좌표(texel)이 존재하게 된다. 따라서 texture image의 점들(texel)을 polygon mesh의 vertex에 할당하고 이전에 진행했던 것과 같은 방식으로 선형 보간한다.

 

texel

 

Texture Coordinates도 역시나 normalize 하는 것이 관례이다. 아래 그림에서 보듯 s축, t축 모두 0과 1 사이의 정사각형 파라미터 범위 안에 존재한다.

texel의 좌표

 

 

위의 그림에서는 6개의 점에 대해서만 texture 좌표(s, t)를 보여주고 있지만 실제로는 모든 정점마다 (s, t) 좌표를 할당한다.  


Surface Parameterization

Surface Parameterization

이러한 방식으로 polygon mesh의 각 vertex에 texture 좌표(s, t)를 할당하는 것을 surface parameterization이라고 한다. 이를 위해 mesh를 평면에 펼치는 작업을 해야한다. 3차원 polygon mesh를 펼치는 것은 왜곡을 가져오는데 이를 최소화하는것도 매우 중요하다. b처럼 입체적인 것을 평면으로 피는 알고리즘은 구체적인 다루지는 않겠다.


Chart & Atlas

Chart and Atlas

polygon mesh 전체를 피는 것이 쉬운 일이 아니다. 얼굴, 상체, 하체 등으로 나눠서 진행해야 한다. 

(a)처럼 펼쳐놓은 것을 chart라고 하고, (b) chart들의 모임을 atlas라고 한다.


Texture Filtering (Magnification & Minification)

위와 같은 polygon mesh가 주어진다면 scan conversion을 하고, 각각의 fragment마다 (s,t)가 만들어진다. 그러한 (s,t)에다가 오른쪽 그림의 texture의 가로, 세로 해상도를 곱해서 s', t'로 들어간다. 그리고 rgb값을 가져온다. 

 

여기서 중요한 한가지 문제는 texture의 크기와 polygon mesh의 크기가 다를 때 발생한다.

즉, 해상도가 다른 경우의 해결에 대한 문제이다.

Magnification

점선 grid에는 원래 texel이 하나씩 있어야 하는데, texel에 비해서 투영된 pixel(fragment)이 훨씬 많을 때가 문제이다.

maginfication 문제는 이처럼 texel보다 pixel이 많을 때 발생한다.

 

Minification

화면에 그려질 때, polygon mesh의 해상도가 50x50 인데 실제는 100x100 이라고 해보자. pixel의 개수랑 texel의 개수랑 비교하면 texel이 훨씬 크다. 그럼 pixel이 large jump를 하게 된다. minification 문제는 이처럼 pixel보다 texel이 많을 때 발생한다.


Filtering for Magnification

먼저 texture image가 작은 경우(pixel이 많은 경우) 텍스처 이미지를 확대해야 한다. 반대로 texture image가 큰 경우 축소해야한다.

 

nearest point samling

texture 확대의 방법은 nearest point sampling, bilinear interpolation등이 있다.

먼저 nearest point sampling은 위의 그림과 같이 n개(여기선 4개)의 픽셀 모두 하나의 texel로 표현하는 방식이다. 가장 가까운 texel을 가져오는 방식으로 간단하지만 blocky image가 만들어진다. 즉 깨지는 현상이 발생한다.

 

bilinear interpolation

다음으로 가능한 방식은 bilinear interpolation이다.

texel의 중심 좌표와 pixel의 투영 좌표를 이용하면, 투영된 pixel의 상대적인 위치를 알 수 있다. (두 texel 사이의 상대적인 위치)

즉, 2번 선형보간하여 해당 pixel의 rgb값을 선택하는 방식이다. 이를 통해 계단 형태의 blocky image를 줄일 수 있다.

 

이 외에도 여러 방법이 있지만 여기서는 두가지 간단한 방법을 소개했다.


Filtering for Minification

다음으로는 texture image가 더 큰 경우 texture 를 축소해야 한다. 즉, texel의 갯수가 pixel의 갯수보다 많을 때이다.

texture가 높은 경우 아무 문제가 없을것 같지만 그렇지만은 않다. 만약 가장 가까운 점들을 단순 선택한다면 이미지의 특징을 잃버어릴 수 있게 된다. 

 

texturing에 참여하지 못하는 texel들이 있기 때문에 발생하는 문제이다. 

 

Minification 예시

(a) 4개의 픽셀 모두 짙은 회색에 둘러 쌓여 있는데, (b) 4개의 픽셀은 모두 밝은 회색에 둘러 쌓여 있다. 둘 픽셀이 다른 이미지를 나타내게 된다. 따라서 Minification 문제가 상당하다.

 

이러한 문제를 앨리어싱(aliasing)이라고 한다. 즉 고주파를 낮은 빈도로 샘플링하는 경우 발생하는 오류를 뜻한다. 이러한 앨리어싱으로 인한 문제를 최소화 하기 위한 방법을 안티 앨리어싱이라고 한다.

 

대표적인 안티앨리어싱 기법으로 Mipmap 방식이 있다.

Mipmap

 

4개의 픽셀을 바인딩해 하나의 픽셀로 만들고 이를 level1 이라고 한다. 다시 level1의 2x2를 하나로 바인딩해 level2 ...level n 까지 단계적으로 texel을 만든다.

 

 

 

level 1에서 pixel과 texel의 비율을 람다라고 하고 로그 람다를 이용해 어떤 level을 사용할 것인지 선택한다.

즉, Down sampling을 하는 것이다.

 

log 람다가 2일때는 딱 맞게 사용할 수 있다. 만약 람다가 정수가 아닌 유리수 라면 어떻게 해야할까?

람다가 3으로 log 람다 = 1.585일때를 가정해보자.

이때는 level 1에서도 2에서도 1대1 mapping이 되지 않는다. 이때는 level 1에서 bilinear interpolation을 진행하고 level2에서도 bilinear interpolation을 진행한다. 그 후 마지막으로 level 1과 level2에 대해 0.585 : 1-0.585의 비율로 다시 보간한다.

 

이런 방식으로 texture filtering을 진행한다. fragment shader가 진행하는 대표적인 두 작업 중 첫번째인 image texturing을 진행하였다. 다음 장에서는 lighting을 배워보자.


Ref.

Introduction to Computer Graphics with OpenGL ES (J. Han)

'☘️ Computer Graphics > Fundamental' 카테고리의 다른 글

CG - Output Merger  (0) 2022.07.20
CG - Lighting  (0) 2022.07.19
CG - Rasterizer  (0) 2022.07.16
CG - Vertex Processing  (0) 2022.07.15
CG - Spaces and Transforms  (0) 2022.07.14
복사했습니다!