원문 http://www.cs.uaf.edu/2007/spring/cs481/lecture/01_23_matrices.html 마지막 "Normal Matrix"의 번역이다.
Normal벡터는 재밌는 녀석이다. 이녀석들은 원근투영 될 필요가 없기때문에 (동차좌표변환이 필요없기 때문에) vec3이다. 그리고 이녀석들은 제대로 scaling되지 않는다 -- 45도의 표면과 45도의 법선벡터가 있을때, glScalef(1,0.1f,1)을 통해 이들을 scaling하면, 표면의 각도는 거의 0도에 가깝게 내려가지만, 이 법선벡터의 각도는 표면으로부터 반대되는 방향으로 90도에 가깝게 '올라간다'.
수학적으로, 표면의 두 점 a,b에 대해 dot(n,b-a)==0 인데, 변환행렬 M을 각 점에 적용했을 때, 법선 또한 여전히 수직이길 원할것이다. 질문은, 어떤 행렬 N이 이러한 결과를 만들어줄 수 있느냐이다. 다시말해서 dot(N*n, M*a - M*b)==0 이되는 N을 찾아야 한다는 말이다.
우리는 단지 내적은 행렬곱으로 표현될 수 있다는 사실을 통해 이를 해결할 수 있다. -- 벡터 x,y에 대해 dot(x,y) = transpose(x)*y 이다.
따라서
transpose(N*n) * (M*a - M*b) == 0 (위처럼 전치행렬과 행렬곱으로 표현하였다.)
transpose(N*n) * M * (a-b) == 0 (변환행렬 M을 모은다.)
transpose(n) * transpose(N) * M * (a-b) == 0 ( trans(AB) = trans(B)*trans(A) 이다.)
OK. 이 결과는 원래의 법선벡터는 표면과 수직했다는 우리의 가정과 비슷한 형태이다 -- dot(n,b-a)==transpose(n)*(a-b)==0. 사실, 다른점은 새로운 행렬이 가운데 박혀있다는것 뿐이다. 만약 가운데의 행렬을 항등행렬로 만들 수 있는 N을 집어낼 수 있다면 새로운 법선벡터 역시 표면에 대해 수직할 것이다.
transpose(N)*M == I (I := 항등행렬)
이건 역행렬의 정의에서 많이 본 형태이다. 즉 "Normal Matrix"라 불리는 N = transpose(inverse(M)) 이다.
GLSL에서는 "gl_NormalMatrix"가 transpose(inverse(gl_ModelViewMatrix))와 같은값이다.
빛 처리 넣어주는데 아무리 해도 카메라 변화에 맞춰 빛이 원하는데로 안움직였다.
매트릭스를 잘못 전달해줬나, 변환 연산을 잘못했나 엄청 해멨는데, 시야공간으로 노멀값 변경해줘야된다는걸 새까맣게 잊고있었다. ㅡㅜ
제대로 시야공간으로 노멀값을 변환해주고 생각해보니, 왜 trans(inverse(M))을 하는지 정확히 이해하고있지 못하더라.
생각난김에 찾아봤는데 정말 명확하게 설명해둔 페이지를 발견했다. 단박에 이해가됬다.
'Graphics Note' 카테고리의 다른 글
Bezier curve (0) | 2014.02.04 |
---|---|
cube map upside-down (0) | 2014.01.22 |
glHint (0) | 2013.12.14 |
Vector/Matrix class (0) | 2013.12.02 |
glRotatef+glTranslatef VS gluLookAt for View transformation (4) | 2013.12.02 |