블로그 이미지
자신의 단점을 메꾸는 것을 단(鍛)이라 하고 자신의 강점을 갈고 닦는 것을 련(鍊)이라 하여, 두가지를 합친 것을 단련이라고 부른다. 붕대마음

카테고리

전체목록 (663)
참고사이트 (8)
Goal (4)
Travel (10)
My Life (102)
Game (35)
Game Review (7)
Game Plan (0)
Books (5)
English (1)
Optimizing (12)
Study (217)
유용한 것들_etc (44)
유용한 것들_func (20)
Unity (48)
Unreal (87)
작업장 (54)
RenderMonkey (6)
정리요망 (1)
따라잡기 시리즈 (0)
링크용 (0)
Total338,297
Today6
Yesterday63

'NORMAL'에 해당되는 글 3건

  1. 2017.02.05 Texture types
  2. 2014.12.10 normal mapping artifacts
  3. 2013.02.07 normal mapping (법선 매핑) (2)

Texture types

Study/Graphics / 2017.02.05 22:09

이 글의 내용은 이곳의 내용중 필요한 부분만 정리한 것입니다.

원문을 보시길 추천합니다.

http://wiki.polycount.com/wiki/Texture_types


텍스쳐 타입

게임모델에 텍스처 처리를 할 때  사용되어지는 몇가지 map 타입이 있다.

모든 경우에, 화면에 렌더링 되는 최종 이미지를 생성하기 위해  다른 map 타입들이 함께 동작한다. 

아티스트들은 각 작업의 균형을 맞추기 위해 이러한 맵들을 동시에 만든다.

대부분의 경우, 이러한 이미지는 투명도(Transparency) 또는 광택(gloss)과 같은

단일 값 슬라이더 대신, 픽셀 단위 수준에서 동작하는 재료 속성을 위한 마스크로 간주될 수 있다.

가장 흔한 타입은 diffuse, emissive, normal, opacity, 그리고 gloss이다.

어떤 타입을 사용할지는 asset 자체와 프로젝트의 Art Direction에 따라 결정된다.

게임의 필요에 따라 다양한 타입들이 하나의 파일로 압축될 수 있다.


Color Maps

가장 일반적인 타입이 diffuse이며 모델에서 보여지는 색상이다.

이 맵은 주어진 asset의 art direction이나 기술적 요구사항 때문에 가장 다양하다.

- Diffuse map(확산 맵)은 표면에서의 빛의 확산반사인 albedo를 만들기 위해 사용된다.

  종종 알베도맵이라고도 불리며 일반적으로 기본 색상만 표현한다.

  diffuse가 유일하게 사용되는 맵이라면 빛, 그림자, 그리고 하이라이트를 사용해서 복잡한 셰이더 효과를

  시뮬레이트 할 수 있으며 이러한 셰이더에서의 diffuse map은 라이트 정보가 작게 들어가거나 없다.

  이러한 효과는 Specular map이나 Normal map같은 다른 형태의 맵의 영향으로 인해 발생하기 때문이다.

  오프라인 렌더링(영화, 상업 등..)에서 diffuse map은 color맵과 별개의 효과를 의미할 수 있는데,

  표면에서 반사되는 빛의 확산을 제어한다.

- Albedo map(반사율 맵)은 PBR 셰이더에서 사용되어지는 좀 더 특화된 확산 형태이며, 표면의 기본 색상만을 나타낸다.

  사실 내가 Albedo map이란 용어를 접한건 그다지 오래 되지 않았는데

  처음 느낌은 Diffuse라는 단어 자체가 Albedo로 바뀐 느낌이었다.

  기존에 Diffuse map(기본 색상 텍스처) 이라고 이해하고 있던 용어를 

  Albedo map(기본 색상 텍스처)라고 용어를 여러군데서 사용하고 있었다.

  완전히 똑같다면 왜 단어를 바꾼걸까?

  그나마 근래에 유행하고 있는 PBR 시스템이 도입되면서 물체의 순수한 색상을

  표현하기 위한 단어가 필요했는데 기존 diffuse map은 순수한 color map 뿐만 아니라

  확산광(난반사)로 음영이 진 것 도 diffuse map으로 불렀다.

- Detail map은 기하물체를 가까이서 볼 때 텍스처의 해상도(또는 그래픽 퀄리티)가 높아 보이도록

   적당한 크기의 텍스처를 반복 시켜 기존 텍스처에 혼합해주는 상세 텍스처이다.

   확대 시 디테일이 있어 보이려면 고해상도의 텍스처를 사용해야 하는데 고해상도 텍스처 대신

   적당한 텍스처에 이 디테일 맵을 섞어서 사용한다.

   밉매핑을 사용하면 타일링된 아티펙트(결함)을 숨기기 위해 detail texture을 중간거리에서 fade out할 수 있다.

   detail map은 자주 Diffuse map, Normal map 과 같이 사용된다.

- Gradient mapColor look-up table은 하나의 색상을 1차원이나 2차원에서 다른 색상으로 매핑하여

   화면이나 모델의 색상을 수정하는데 사용할 수 있다. (ex : color correction, ramp texture ... etc)

   이들은 일반적으로 global asset이며 특정 모델로 제한되지 않는다.

- color variation(색의 변형)이나 사용자 정의 asset, 또는 재질 영역을 위한 Masking은 Color map으로 간주할 수 있다.


Transparency Maps

- Transparency maps, 또는 opacity로 알려져 있으며, 표면의 불필요한 부분을 제거하는 사용되며

   보통 알파블렌딩으로 사용한다.  예 : 불, 풀, 머리카락, 연기, 물, 창문 등..


Bump Maps

- Bump maps은 지오메트리의 음영을 수정하는 2D 흑백 맵으로 일반적으로 표면의 디테일 표현에 사용된다.

- Normal maps은 정점의 노멀을 수정하여 보다 세밀한 지오메트리를 표현하는 3D bump map이다.

- Radiosity normal maps은 light map과 normal map을 혼합한 특수한 맵이다.

http://egloos.zum.com/cagetu/v/5658605

- Displacement maps은 bump와 비슷하지만 높이정보를 저장해서 렌더링 시 지오메트리를 변형하여

  음영과 실루엣을 수정한다.

- Height maps은 일반적으로 지형 메시의 정점을 위 아래로 이동하여 변형시키는데 사용된다.

- Vector displacement maps은 height의 확장이지만 모든 축에서 정점을 변형 할 수 있다.

- Wrinkle maps은 구현에 따라 다르지만, 케릭터가 특정 방향으로 구부리면 옷에 주름이 

  생길수 있는 국한된 bump값을 저장한다.


아래부터는 bump 종류가 필요없지만 비슷한 효과를 낸다.

- Parallax maps은 다른 텍스처를 표면에 따라"슬라이드"하여 물체의 높이와 깊이를 시뮬레이팅 한다.

  http://mgun.tistory.com/1536

- DuDv maps은 메시의 UV를 수정하여 픽셀단위로 다른 텍스처를 왜곡한다.

- Flow maps은 DuDv 와 흡사한데, 물의 흐름이나 이방성의 하이라이팅과 같은 방향 기반 왜곡을 정의한다.

- Curvature maps은 흑백으로 볼록/오목함을 저장한다.

http://blog.naver.com/blue9954/220424879221

Specular maps

- Specular maps은 표면의 반사율을 제어하고 반사모양을 조정할 수 있다. 

  Specular는 일반적으로 장면에서 가장 밝은 광원의 반사만을 시뮬레이션 한다.

  Specular map은 또한 표면에서 environment maps(환경맵)이 얼마나 많이 보여질지를 제어하는데

  사용할 수 있다.

- Gloss maps은 specular highlight가 얼마나 넓게 또는 좁게 보여질지를 제어한다.

- Roughness maps은 PBR 시스템에서의 Gloss maps으로 표면이 얼마나 거친지 또는 부드러운지를 나타내며

  Microsurface(미세면)이라고도 불린다.

- Reflectivity(반사율)은 PBR 시스템에서 Specular 이며, 표면에서 얼마나 많은 빛이 반사되어 나오는지를 나타낸다.

- Metallic maps은 PBR에서 Reflectivity(반사율)의 대안으로, metallic(금속)이나 non-metallic(비금속)으로 재질을

  표현함으로써 다르다.

  이 방법에서, Albedo map은 non-metals와 규칙적으로 작동하지만 metal 영역에 대한 reflectivity(반사율)

  역활을 한다.

- Anisotropic maps(비등방성 맵)은 실시간 조명에서 specular highlight의 모양을 제어하며,

  종종 머리 음영에서 사용된다.  

- Brdf maps은 카메라 각도를 빛의 값에 매핑하여 반사를 제어한다.

- Fresnel / Rim light maps은 벨벳이나 미세한 머리카락과 같이, 표면의 극한 각도에서

  나타나는 빛의 양을 제어하는데 사용된다.


Environment Maps

Environment maps은 일반적으로 표면반사에 사용되며, 반사된 모델의 주변모습을 보여준다.

이는 실제 장면의 정확한 모습을 렌더링하지 않는 무척 저렴한 방법이며 

일반적으로 실시간으로  렌더링 하는것은 무척 느리다.

- Cube maps은 육면체에 전경을 매핑시키는 여섯개의 모양을 가지는 가장 일반적인 타입이다.

- Diffusely convolved cube map은 블러가 된cube map으로 정확한 반사보다 더 나은 주변광을 표현한다.

- Spherical environment mapLit sphere 또는 MatCap로도 알려져 있으며,

  빛과 색상값을 반구의 각도로 매핑하는 단순한 이미지 반사다.

  관련 링크

  - Sphere mapping



Light Maps

Light maps은 화면에서 표면에 미리 계산된 복잡한 라이팅을 저장한다.

- Ambient occlusion maps은 표면에서 바운스 되는 주변광을 미리 계산된 것이다.

  참고 : http://mgun.tistory.com/2115

- Cavity maps은 ambient occlusion의 좁은 버전이며, 어두우 그림자는 틉과 날카로운 모서리에서만 나타난다.

- Emissive map은 Glow 또는 Self-illumination으로도 알려져 있으며 컴퓨터 모니터, 밤의 차량의 계기판, 

  또는 마법효과 처럼 표면이 빛을 발하는 것을 흉내낸다.

Radiosity normal maps은 light map과 normal map을 혼합한 특수한 맵이다.

  그래서 위의 Bump map으로도 분류할 수 있다.

- Thickness maps은 표면이 얼마나 두꺼운지/얇은지의 측정이다.

  일반적으로 뒤에서 빛이 들어올 때 고양이의 귀나 쫙 펴진 가죽같은 표면을 통과하는 가짜 빛에 사용된다.


Other Maps

- Texture Coordinates는 UV map으로도 알려져 있으며 2D 이미지를 굴곡이 있는 3D 모델링에 매핑하게 되면

  이미지의 일그러짐이 생기게 되는데 이를 바로잡아 주기 위해 모델 자체 내의 좌표체계에 맞춰 좁은부분

  또는 넓은 부분을 맞추어 이미지의 일그러짐을 최소화 시키는 작업이다.

- SSS/ Subsurface Scattering maps은 피부나 왁스같은 반투명 내부에서 빛이 bounce 되는 

  행동을 흉내낸다.

- Subdemal maps은 skin shader에서사용되며, 피부 아래의 레이어를 표현한다 : 피주조직, 혈색과 혈관.

'Study > Graphics' 카테고리의 다른 글

depth-precision-visualized  (0) 2018.01.31
디더링 (Dithering)  (0) 2018.01.26
Texture types  (0) 2017.02.05
rgbm  (0) 2016.12.29
Efficient Gaussian blur with linear sampling  (0) 2016.10.22
Blur 1  (0) 2016.10.12
Posted by 붕대마음





예전에 디자이너가 게임 케릭터를 확대해 보면 위와 같이 specular가 각져보인다고 말했다.
당시에는 일정이 바빳고 어차피 모바일게임에서 케릭터를 그정도 까지 확대할 일이 없어서 
그냥 넘어갔었는데 어쩌다 보니 눈에 보여서 살펴보게되었다.

우선 원인은 normalmap으로 부터 얻은 normal값이 0~1의 범이기 때문에 *2 -1의 연산이
들어가게 되는데 이 과정에서 normalize를 안해주었던 것이다.
vector를 정규화 해 주는 이유는 벡터의 크기를 고려하지 않고 벡터의 방향만을
고려하기 위한 것이다. (머 이런저런 이유가 더 있을까?)
무튼 그래서 정규화를 해 주면 위의 오른쪽 사진처럼 블럭모양의 결점은 안생긴다.
그런데 이 문제를 해결하기 위해 검색을 하다보니 Lyon이라는 specular model에 대한
아티클을 발견하게 되었다.
이는 하프벡터와 노말을 내적한 후 specular power값으로 지수연산하는 블린 퐁과
조금 다른 연산을 한다.

이 방식은 블린퐁 모델과 매우 비슷한 결과값을 만드는데 거리값과 훨씬 작은
specular power 연산을 한다.(Specular power로 지수연산을 하지 않는다.)

자세한 내용은 아래 링크된 pdf를 보면 된다.(난 마지막 부분 소스만 봤지만.ㅡㅡ;)






reference links : 
- http://theinstructionlimit.com/tag/blinn-phong
- http://jalnagakds.tumblr.com/post/25825085620/phong-blinn-phong 
- Lyon model pdf file

'Study > Graphics' 카테고리의 다른 글

normal map compression  (0) 2016.06.13
Semantics  (0) 2016.05.09
normal mapping artifacts  (0) 2014.12.10
tangent space, 접선 공간  (0) 2014.04.07
DXT 압축  (0) 2013.03.15
BRDF (Bidrectional Reflectance Distributing Function)  (0) 2012.12.06
Posted by 붕대마음

specular map : 각 텍셀에 정반사광을 보여줄 정도를 정의
normal map : 법선벡터의 방향을 나타낸다.
                    높이맵(height map)에서 기복을 계산하고, 그 높이의 기복으로부터 법선벡터를
                    계산하여 텍스처에 기록.
                    이렇게 각 픽셀에 사용할 법선 정보를 담고 있는 텍스처를
                    법선맵(normal map)이라고 하고 법선맵을 이용해서
                    조명을 계산하는 기법을 법선매핑(normal mapping)이라고 한다.                   
height map : 법선방향의 기복 크기를 기록한 텍스처, 높은곳이면 하얗게,
                      낮은곳이면 검게 그려진다.

법선벡터의 중요성 : 
확산광에서는 법선과 광원벡터만 사용해서 조명의 강도를 계산.
   ex : Lambert( N · L )
반영반사광에서도 법선벡터가 중요.
   ex : Phong, Blinn Phong ( N · L )

문제점 : 
일반적으로 법선은 정점마다 있어서 픽셀단위 조명에서 이러한 정점에 정의된
법선 벡터를 보간해서 사용
.
하지만 이 방법은 솟아 오른곳이나 울퉁불퉁한 곳에는 폴리곤 수를 늘려
하나하나의 정점과 법선을 
모델러가 조절해 줘야 한다는 단점이 있다.
결론은, 아무리 하이폴리곤 오브젝트를 사용하더라도 정점과 정점 사이는 선형으로 보간되기 떄문에
굴곡의 표현이 어려운데 이 부분을 픽셀셰이더에서 매핑을 이용해 해결.
변경된 법선을 이용하여 정점과 정점 사이에 주름과 돌기같은 음영표현을 한다. 

대안 : 
텍스쳐를 이용해서 간편하게 폴리곤의 삼각형 크기보다 상세한 기복을 표현할 수 있도록 한다. 

즉, 법선맵핑이란 거친질감을 표현하기 위해 특수한 텍스쳐를 사용해 법선벡터를 섭동시켜 픽셀마다 조명계산을 
하게 하여 기복이 있는 것처럼 보이게 한다. 

만들어 보기.
텍스처는 R,G,B채널이 있으므로 각 X,Y,Z값을 대입하여 저장한다.
하지만 텍스처의 각 채널에 가질 수 있는 값의 범위는 0~1 이다.
이곳에 정규화한 단위벡터를 넣어주면 된다.
단위벡터는 크기값이 1인 벡터인데 크기값이 1이라는 것은 (1,0,0)일 수도 있지만
(-1,0,0)이 될 수도 있다는 말이 된다.
즉, 정규화된 법선벡터의 범위가 0~1이 아니라 -1~1이 되어 버리는 것이다.

그렇다면 0~1의 범위만을 포용하는 텍스처에 -1~1의 값을 가지는 벡터값을 어떻게 넣을 것인가?
담을 바구니를 크게 만들지 못한다면 넣을 물건을 작게 만들면 되지 않을까?
즉, -1~1을 0~1의 값으로 변환시키면 된다.
법선맵 RGB = 법선벡터 XYZ * 0.5 + 0.5
이렇게 하면 -1은 0에 맞추어지고 1은 1에 맞추어 진다.

반대로 법선맵 RGB로부터 법선벡터 XYZ를 구하고자 한다면?
위의 식 중 *0.5 + 0.5를 넘겨주면 된다.
법선맵 RGB - 0.5 = 법선벡터 XYZ * 0.5
2*(법선맵 RGB - 0.5) = 2*(법선벡터 XYZ * 0.5)
2*법선맵 RGB - 1.0 = 법선벡터 XYZ * 1.0 = 법선벡터 XYZ
법선맵 RGB * 2 - 1.0 = 법선벡터 XYZ

Toon Shading에서는--------------------------------------------------------
Toon Shading에도 이와 비슷한 방법을 사용했었는데 결과 diffuse값이 0~1인 값을
0, 0.2, 0.4, 0.6, 0.8, 1.0 과 같이 0.2 단위의 값만을 가지도록 만들기 위해
diffuse*5를 곱해서 0~5의 값을 가지게 만들고 ceil()을 사용하여
딱 맞게 0,1,2,3,4,5 의 값중 하나만 가지도록 올림연산 한다.
그리고 이 값들을 5로 나누어 주면 0, 0.2, 0.4, 0.6, 0.8, 1.0의 값으로 만들 수 있다.
----------------------------------------------------------------------------

이렇게 법선 벡터를 텍스처에 저장하는데 이 법선벡터가 가지는 x,y,z의 의미를 생각해 보자.
법선벡터가 (-1,0,0)의 값을 가진다면 이 벡터는 어딜 향하고 있는 것일까?
x,y,z의 값이 의미가 있으려면 이 값을 표현해 줄 수 있는 공간이 있어야 한다.


위 그림은 법선매핑에서 사용되는 공간의 xyz 좌표계다.
표면에 수직인 방향이 z이며 오른쪽이 x고 y는 이 두 방향에 직각인 방향이다.
그런데 여태까지 해오던 로컬공간, 월드공간, 뷰공간, 프로젝션 공간같은 것중 이 공간은 무슨 공간일까?


육면체의 왼쪽과 오른쪽 면에 동일한 법선맵을 사용한다고 가정한다면 왼쪽면의 z방향(0,0,1)은 왼쪽을 향하고
오른쪽면의 z방향(0,0,1)은 오른쪽을 향한다.
동일한 벡터이지만 가리키는 방향이 다르다?
현재까지 사용한 공간이랑 개념이 조금 다른데 이전 공간들은 물체마다 정의된 것이라면 이 공간은
표면마다 정의
되어 있는 것이다.
"표면의 바깥쪽 방향을 법선의 +z로 한다"는 명제를 사용하여 법선맵을 만들기 때문에
표면마다 다른 공간이 존재하는데 이 공간을 접선공간(tangent space) 또는 표면공간이라고 한다.

이제 이 법선맵에서 법선벡터를 가져와 라이팅을 계산하면된다.
그런데 문제가 하나 있다.
이전 툰셰이딩에서도 말했듯이 같은 공간의 것들끼리 연산을 해주어야 하는데
법선정보가 접선공간에 존재한다는 것이다.
즉, 법선정보를 사용하고 한다면 공간변환을 해 줘야 한다는 것이다.
그렇다면 공간변환을 위해 필요한 행렬연산은 어떻게 만들어줘야 하는가?
접선공간을 구성하는 행렬은 좌표축 3개만 있다면 쉽게 만들 수 있는데
우선 정점의 법선인 Z, 표면위를 달리는 축인 X, 그리고 X와 Z에 직각인 Y를 구해야 한다.
Z는 법선자체 이므로 그대로 사용하면 되고 X는 표면위의 정보에서 구해올 수 있는데
UV좌표가 표면위에 정의되어 있기 때문에 U와 V중 하나를 가져와 그것을 X로 사용하면 된다.
그래서 이 X를 접선(tangent)라고 한다.
X와 Z에 동시에 직각인 Y는 외적을 통해 쉽게 구할 수 있는데 이 축을 종법선(binormal)이라고 한다.
접선 T = (Tx, Ty, Tz)
종법선 B = (Bx, By, Bz)
법선 N = (Nx, Ny, Nz)
로 표시할 수 있는데 접선공간변환에 사용하는 행기준 행렬은 (d3d)
| Tx Ty Tz |
| Bx By Bz |
| Nx Ny Nz |
이렇게 표시 할 수 있고 열기준 행렬이라면 (open gl)
| Tx Bx Nx |
| Ty By Ny |
| Tz Bz Nz |
요렇게 표현할 수 있다.

이제 말로만 계속 언급했던 normal map(법선맵)을 보도록 하자.

법선맵은 왜 항상 푸른계열의 색상을 유지할까?
RGB채널중 B 채널은 법선벡터의 Z와 매칭이 되는데 법선벡터의 Z는 항상 표면의 바깥쪽을 가리키는 방향이기 때문에
벡터의 범위인 -1~1의 범위가 아니라 0~1의 범위를 가진다.
그런데 이전에도 말했듯이 벡터범위인 -1~1를 텍스처 범위인 0~1로 우겨넣기 위해 *0.5, +0.5를 시행하므로
Z값은 범위가 0.5~1.0이 되어 항상 Z값은 최소한 절반이상 들어가 있게 된다.
그래서 B값이 유독 크기 때문에 파란색을 띄게 된다.


돌판의 오른쪽을 보면 붉은색의 하이라이트가 있고 왼쪽은 어두워 진다.
실제 이 돌판은 분명 튀어나와 있는데 오른쪽 붉은색 하이라이트 부분의 경우는 오른쪽을 향하는
법선을 가지고 있을 텐데 이 값이 (1,0,0)이라서 변환 후 (1, 0.5, 0.5)가 되서 붉은색을 띄고
왼쪽은 당연히 왼쪽을 향하고 있을 것이며 왼쪽은 (-1,0,0)이 되고 이는 변환시 (0, 0.5, 0.5)가 되는 것이다.

위 아래도 마찬가지로 위쪽은 당연히 위쪽으로 법선이 향할것이고 아래는 아래쪽 방향으로 향할 텐데
아래쪽 법선의 값은(0,1,0)이라서 변환하면 (0.5, 1.0, 0.5)가 되어 녹색을 띄고 위쪽은 (0,-1,-0)이라서
변환하면 (0.5, 0, 0.5)가 되어 녹색이 사라지면서 어둡게 된다.

이제 렌더몽키로 실제 구현을 해 보자.
중요한건 이전 diffuse를 구하던 것을 vertex shader가 아닌 pixel shader에서 해야 한다는 것이다.
diffuse를 구한 다는 것은 light dir과 normal을 내적한다는 말인데 여기에서는 normal을
texture에서 구해서 사용하기 때문에 texture의 텍셀값을 얻어올 수 있는 pixel에서 diffuse를 구해야 한다.
즉, 법선매핑을 사용할 때 정점에서 가져오는 법선은 조명에 사용하지 않는다.
그리고 Reflection값도 http://mgun.tistory.com/1337 요기 링크를 보면 알겠지만 E와 N의 내적으로 구해진다.
N을 정점의 노말로 사용하지 않고 텍스처에서 사용하므로 Reflection값도 픽셀에서 구할 수 밖에 없다.

그리고 접선공간을 변환하기 위해 지정한 세 데이터(법선, 접선, 종법선)도 월드 공간에 있어야 한다.
조명계산에 필요한 것은 결국 Light Dir(입사광 벡터), View(카메라 벡터), Normal(법선벡터)다.
그런데 올바른 법선이 텍스처에서 읽어와야 하는데 텍스처는 접선공간에 존재하므로
이를 월드공간으로 변환해 줘야 조명계산하는데 필요한 모든 요소들을 한 공간에 묶을 수 있다.
그러려면 픽셀 셰이더에서 법선/접선/종법선 벡터를 사용해서 접선공간에서 월드공간, 또는
월드공간에서 접선공간으로 변환하는 행렬을 만들 수 있다는 말이 된다.

struct VS_OUTPUT
{
   float4 mPosition : POSITION;
   float2 mUV: TEXCOORD0;
   float3 mLightDir : TEXCOORD1;  
   float3 mViewDir: TEXCOORD2;
   float3 T: TEXCOORD3;
   float3 B: TEXCOORD4;
   float3 N: TEXCOORD5;

};

픽셀셰이더에서 법선텍스처에서 법선을 읽는다.
float3 tangentNormal = tex2D(NormalSampler, Input.mUV).xyz;

텍스처에서 읽어온 값은 0~1이다.
하지만 실제 법선벡터의 범위는 -1~1이다.
0~1의 범위의 값을 -1~1로 다시 바꿔주기 위해서는 *2를 하여 0~2로 만든 후 -1을 하여 -1~1로 설정한다.
tangentNormal = normalize(tangentNormal*2-1);

접선공간 법선을 구했는데 이 녀석은 말 그대로 접선공간에서의 법선값이다.
이를 월드공간에서의 값으로 변환 해 줘야 라이팅 계산시 사용할 수 있다.
그래서 T,B,N벡터로 행렬을 하나 만든다.
float3x3 TBN = float3x3(normalize(Input.T), normalize(Input.B), normalize(Input.N));

그런데 이 TBN 행렬은 월드공간을 접선 공간으로 변환하는 행렬이다.
지금 필요한건 접선공간을 월드공간으로 변환시켜줄 행렬이다.
TBN의 역행렬을 사용해야 하는데 직교행렬의 역행렬(Inverse)은 전치행렬(Transpose)과 같다.
그렇다면 직교행렬이란 무었인가?


정리해 보면 직교행렬이란..
1. 행렬의 각 행벡터가 서로 직교해야 한다.
2. 각 행벡터의 크기가1이어야 한다.
3. 두 행벡터의 내적은 항상 0이어야 한다.

우선 T,B,N은 모두 normalize했으므로 벡터의 길이는 1인것은 당연하고
세 벡터가 서로 직교하므로  내적은 항상 cos90도, 즉 0이 나오므로 TBN은 직교행렬이다.

그렇다면 전치행렬은 무었인가?
전치행렬은 단순하게 행렬의 행과 열을 바꾸는 것을 말한다.

TBN은 직교행렬이고, 월드공간을 접선공간으로 변환시켜준다.
이를 접선공간에서 월드공간으로 바꿔주는 행렬로 바꿔주기 위해
TBN의 역행렬을 구해줘야하는데 TBN은 직교행렬이므로 역행렬과 전치행렬은 같다.
HLSL에서 전치행렬을 구하는 함수 transpose()가 미리 준비되어 있다.
TBN = transpose(TBN);

이제 접선에서 월드공간으로 변환시킬 수 있는 행렬을 구했으니 접선공간에서 구한 normal값을
월드공간으로 변환시켜 주자.
float3 worldNormal = mul(TBN, tangentNormal);

오잉? 먼가 좀 이상한 부분이 있다.
여태까지는 mul(벡터, 행렬)의 방식으로 곱했었다.
ex) Output.mPosition = mul( Input.mPosition, gWorldViewProjectionMatrix );
그런데 여기에서는 왜 mul(TBN(행렬) , tangentNormal(벡터)) 인가?
이유는 TBN을 만들 때 float3x3 생성자를 사용했기 때문인데, 이를 사용하면
행기준 행렬이 나온다.
그와 반대로 SetMatrix()함수를 통해 CPU로부터 건네받은 행렬은 열기준 이다.
행기준 행렬은 mul(행렬, 벡터)의 순서로, 열기준 행렬은 mul(벡터, 행렬)의 순서로 곱한다.

이젠 월드상의 노말값도 구했겠다 나머지는 이전에 하던 것과 같다.
float4 albedo = tex2D(DiffuseSampler, Input.mUV);
float3 lightDir = normalize(Input.mLightDir);
float3 diffuse = saturate(dot(worldNormal, -lightDir));
diffuse = gLightColor * albedo.rgb * diffuse;
diffuse 텍스처로부터 diffuse값을 구하고 normal과 light를 내적하여 조명도 계산하고
거기에 추가적으로 light의 color도 고려해서 최종 diffuse값을 구해주면 된다.

반사값은 미리 제공해 주는 reflect()함수를 사용해서 구하면 되고
float3 reflection = reflect(lightDir, worldNormal);

specular은 반사R과 camera라 V를 내적해서 하이라이트를 구하고
specular = saturate(dot(reflection, -viewDir));
specular = pow(specular, 20.0f);

specular 텍스처를 통해 specular의 강한정도와 light의 color을 고려해서 최종 specular값을 구한다.
float4 specularIntensity = tex2D(SpecularSampler, Input.mUV);
specular *= specularIntensity.rgb * gLightColor; 


Normal.rfx


Normal Mapping : 법선맵 사용, 법선맵이 입혀진 측면에서 보면 입체감이 없다.
Parallax Mapping : 법선 외에 높이맵(height map)을 사용하여 문제점 해결
Parallax Occlusion Mapping : 인접픽셀과의 높이차를 구한 뒤 그에 따라 그림자를 입히는 기법.


위의 사진은 view와 light를 tangent 공간으로 바꾼 후 계산한 diffuse + normal + specular의
결과물이다.

Default.rfx




참고 : 
- Displacement Mapping과 Parallax Mapping의 차이
  http://mgun.tistory.com/122
- Surface Texture Mapping
  http://mgun.tistory.com/140
- mapping
  http://mgun.tistory.com/280
- 사용 리소스
  http://www.bencloward.com/shaders_offset.shtml
- kw x-port
  http://www.kwxport.org/
-탄젠트공간
  http://mgun.tistory.com/1289
-법선 매핑
http://blog.naver.com/sorkelf/40157218010

ps. 문제가 되는 이미지나 링크는 알려주시면 자삭하겠습니다.


'RenderMonkey' 카테고리의 다른 글

Shadow Mapping  (0) 2014.01.11
fresnel  (0) 2013.10.22
normal mapping (법선 매핑)  (2) 2013.02.07
기본적인 반사 벡터  (0) 2013.02.02
lambert  (3) 2013.01.31
흐음...렌더몽키라..  (0) 2013.01.29
Posted by 붕대마음

최근에 달린 댓글

최근에 받은 트랙백

글 보관함