momodudu.zip

#6 Texturing 본문

Graphics/OpenGL

#6 Texturing

ally10 2019. 9. 26. 18:51

이번 포스팅은 texture 매핑에 관한 포스팅이다.

 

실제로 texturing이라고 하면, image, 즉 color값만을 mesh에 입히는것으로 생각할 수 있는데 실제 texture는 color뿐만아니라 normal이나 depth도 가질 수 있다.

 

<Texture Filtering>

어쨌든, texture filtering란 한 mesh의 정점(x,y)에 대해서 (u,v)를 mapping하면 텍셀(tx,ty)를 얻을 수 있는데, uv는 [0,1]로 normalize된 정규화 좌표이므로 (x,y)에 uv를 곱하게 되면 텍셀 좌표는 실제로 부동소수점 값이다. 이를 처리하기 위해서 한 텍셀을 처리할 때 주변 텍셀들의 정보를 참고하고 결합하여 현재 텍셀을 결정한다. 이게 바로 texture filtering의 정의다.

 

texture filtering에는 크게 3가지 기법이 있다.

 

1) texture와 mesh의 size가 1:1 대응이 되는 경우

위 그림처럼 mesh와 texture의 size가 거의 비슷하거나, 1:1 대응이 되는 경우이다. 이 경우에는 특별한 처리 없이 각 vertex가 uv 정수값에 가깝게 대응이 될것이므로 아무런 문제가 없다.

 

2) Magnify - texture size가 mesh에 비해 작아서 texture 확대가 필요한 경우

조금 직관적으로 설명해보자면, mesh 크기가 texture보다 크므로 texture를 확대할것이다. 텍셀이 1단위의 격자로 되어있다고 가정해보면, 1)의 경우에는 texture를 늘리지 않았으므로 텍셀1당 pixel 1이 대응 된다고 하자.

그렇다면 2번의 경우에는 똑같은 texture를 늘리게 될 것 이므로 텍셀 1당 여러개의 pixel이 대응이 될 것이다.

즉, 하나의 texel이 여러개의 pixel을 결정짓게 되는 것이다. 이 결과로, 일명 모자이크 현상이 생기게 된다. 즉 이미지 품질이 좋지 않아진다.

 

3)Minify - texture size가 mesh에 비해 커서 texture 축소가 필요한 경우

반대의 경우는 어떨까? 이 경우에는 반대로 하나의 pixel이 여러개의 텍셀의 영향을 받게 될것이다. 이 결과로 이미지 텍스처링 자체가 제대로 되지 않는다. 2)의 모자이크 현상으로 살짝 깨져보이는건 고사하고, 렌더링 결과물 자체가 의도했던것과 전혀 다른것이 나올 수 있다는 얘기다. 이 문제를 aliasing이라고 하며, 해결 기법으로 그 유명한 anti-aliasing이 필요하다.

 

 <Mip-mapping>

anti-aliasing의 대표적인 기법이다. 위에서 얘기한 minify의 문제 원인은 texture가 primitive보다 한참 크기 때문에 발생하는 문제였다. 이를 해결하기 위해서는, 간단한 해법으로는 당연히 텍스쳐 크기를 줄이면 된다. 이 기법이 바로 mip-mapping이다.

하나의 image(보통 2^n*2^n size)를 가지고, 2*2의 텍셀 블록 하나를 다음 레벨의 1개의 텍셀 블록으로 할당하여 크기를 1/4씩 계속해서 줄여나간다. 이것을 down-sampling이라고 한다. 이런식으로 계속 down-sampling을 하다보면 결국 마지막엔 n+1레벨의 이미지를 얻을 수 있을 것이다. 이 down-sampling결과를 피라미드 형식으로 모아놓은것이 바로 mip-map이다.

 

이 밉맵 텍스처를 가지고, 확대 필터링의 경우에는 mip-map level 0의 image만 사용하고, 축소 필터링의 경우에는 얼마나 축소되는가에 따라 여러개의 mip-map level image를 사용하게 된다.

 

이 과정은 OpenGL 내장으로 모두 지원된다. 이미지로부터 텍스처를 생성하는 과정에서, 아래와 같이 지정해주면 된다.

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	
	glGenerateMipmap(GL_TEXTURE_2D);

magnify/minify filtering 방식을 먼저 지정해준다. 위에서 설명한것처럼 확대 필터링은 linear하게 하면 되고, 축소의 경우에는 linear하게 하되, mipmap을 사용할것이라고 알려준다.

그리고 밉맵 텍스쳐를 생성한다. 실제로 차이를 가져와봤다.

왼쪽이 일반 필터링이고, 오른쪽이 밉맵필터링을 사용한 결과물이다. 실제로 좀 더 blend 하게 렌더링 된 결과물을 확인할 수 있다. 이건 간단한 예제라서 굳이 mipmap을 쓸필요가 있냐 싶겠지만 실제로 이런 aliasing 사례를 실무에서 접했었는데 진짜 보기싫음.. 렌더링 품질이 확실히 떨어진다.

 

 

<Compression Texture>

bmp이미지는 무압축 포맷이다. 즉 손실도 없고 압축도 하지 않는다. 그러나 실제로 시스템이 돌아갈 땐 압축된 이미지를 사용하는것이 텍스처 로딩에도 빠르고 잡아먹는 메모리도 작아서 실제 상황에서는 압축된 텍스처를 많이 사용한다. 특히 3D Graphics 엔진에서는 Real-Time rendering을 위해서는 빠른 texture sampling을 위해서 최적화된 포맷을 사용한다.

 

대표적으로 astc는 가변 블록 크기로 압축된 rgb(a) texture, 고압축 텍스처인 pvrtc, 안드로이드의 알파채널이 없는 default texture로 사용되는 etc 등등.. 이런 압축 포맷은 엔진이 돌아가는 OS와 사용하는 api에 따라 적절하게 선택해야한다.

이런 텍스처들은 압축 시간이 길어서 그렇지, 실시간 렌더링에 자주 사용된다.

 

음.. 이 각각 압축 텍스처에 대한 자세한 설명은 나중에 추가로 해야될 듯 하다.

어느 원리로 압축되고, 장단점이 뭔지에 대해서 정도는 파악이 필요하다.