2023. 7. 14. 23:03ㆍ컴퓨터 그래픽스/HLSL
7장은 normal mapping에 대한 내용이다.
어떻게 물체의 울퉁불퉁한 정도를 polygon을 더 넣지 않고 나타낼 수 있을까? 울퉁불퉁한 정도를 texture을 이용하여 조명 계산을 통해 울퉁불퉁하게 나타낼 수 있다. 이것들은 pixel shader에서 나타내줄 것이다.
여태껏 해왔던 표현과 울퉁불퉁한 표현
우리가 이런 울퉁불퉁함을 나타내기 위해서 쓸 것은 normal vector들이다. 이런 normal vector들은 모델링 과정에서 다 가져오게 될 것이다. 즉 normal texture에서 가져오게 된다. normal vector들은 그런데 normalize 되어 있는 벡터들이므로 -1 ~ 1 의 범위를 갖는다. 그러나 texture 상에서는 rgb 값들을 저장하는데 rgb의 범위는 0 ~ 1의 범위이다. 그러므로 0~ 1로 맞춰주기 위해서
normal texture = normal vector * 0.5 + 0.5으로 rgb를 얻게 된다.
normal vector를 그러면 어떻게 얻는가 보면
normal map에서 쓰일 vector는 기존의 world 좌표나 view 와는 다른 새로운 좌표계이다.
왜냐하면 위의 사진처럼 표면에 따라 같은 값이지만 방향이 다르기 때문이다. 그러므로 새로운 좌표계에서 구해주어야 한다. 이것을 tangent space라 한다.
tangent space는 정점과 그 정점의 normal, 그 정점에서의 접선 tangent, normal과 tangent와 서로 수직인 binormal로 이루어져 있다.
normal들은 모델링 과정에서 구해지고, tangent 또한 구해서 가져온다. 가져온 것들을 우리는 world 좌표계로 다시 바꿔서 pixel shader로 보내면 되는 것이다.
다시 말해, 모델링 과정에서 나온 normal과 tangent는 object space이므로 world matrix와 계산하여 world로 바꿔주는 것이다.
우리가 쓸 normal map은 tangent space 상에서의 normal vector들이므로 이것들을 모두 world 좌표로 바꿔서 world에서 계산하거나 모두 tangent space로 바꿔서 계산해서 가져오거나 해야한다.
tangent space 좌표계 matrix이다.
위의 행렬은 직교행렬이므로 열 벡터, 행 벡터 각각 크기가 1이다.
그리고 위의 행렬의 transpose를 하게 되면
바로 역행렬이 되므로 tangent → world 변환 행렬이 된다.
열벡터끼리 서로 수직이다.
행기준 행렬인지 열기준 행렬인지 알아야 계산 시에 맞게 써줄 수 있다.
행기준 행렬
A(Row) =
| a00 a01 a02 a03 |
| a04 a05 a06 a07 |
| a08 a09 a10 a11 |
| a12 a13 a14 a15 |
열기준 행렬
A(Col) =
| a00 a04 a08 a12 |
| a01 a05 a09 a13 |
| a02 a06 a10 a14 |
| a03 a07 a11 a15 |
행 기준 행렬 계산
| x' y' z' w' | =
| x y z w | × | a00 a01 a02 a03 |
| a04 a05 a06 a07 |
| a08 a09 a10 a11 |
| a12 a13 a14 a15 |
x' = xa00 + ya04 + za08 + wa12
y' = xa01 + ya05 + za09 + wa13
z' = xa02 + ya06 + za10 + wa14
w' = xa03 + ya07 + za11 + wa15
열 기준 행렬 계산
| x' | | a00 a04 a08 a12 | | x |
| y' | | a01 a05 a09 a13 | × | y |
| z' | = | a02 a06 a10 a14 | | z |
| w' | | a03 a07 a11 a15 | | w |
x' = a00x + a04y + a08z + a12w
y' = a01x + a05y + a09z + a13w
z' = a02x + a06y + a10z + a14w
w' = a03x + a07y + a11z + a15w
어느 기준이냐에 따라 앞에다 곱해줄지 뒤에다 곱해줄지 다르다
float3x3의 생성자를 이용하게 되면 행 기준 행렬로 나오게 되고, dx 같은 곳에서 setMatrix를 이용하게 되면 열 기준 행렬로 나온다.
이제 normal map에서의 vector를 world로 가져오든, 현재 world의 값들을 tangent space로 옮기던 해서 diff와, spec를 새로운 normal을 이용해서 계산해서 pixel로 나타내면 된다.
환경 mapping
환경 mapping은 미리 주위 환경에 대한 텍스쳐를 가져다가 실시간으로 렌더링하여 텍스쳐를 입히는 방식이다. cubmap과 같다.
환경 mapping은 6개의 텍스쳐를 박스로 만들고 object를 그 안에서 rendering하게 되는데 그러면 하나의 작은 세상이 만들어지는 것이다.
환경 mapping은 view vector에 영향을 받는데 view vector에서 반사된 지점이 환경 texture의 texel 위치를 가져오게 된다. 6면에 대한 반사들이 존재할 것인데 이것은 HLSL에서 알아서 처리해준다
float3 environment = texCUBE(EnvironmentSampler, viewReflect).rgb;
texCUBE함수로 texture와 view의 반사벡터를 매개변수로 넣어주면 texel을 가져오게 되는 것이다.
그리고 마지막에 색을 표현할 때는 ambient, diffuse, specular 와 함께 더해준다.
return float4(ambient + diffuse + specular + environment* 0.5f, 1);
'컴퓨터 그래픽스 > HLSL' 카테고리의 다른 글
재질에 따른 반사양 조절, toon shading (0) | 2023.07.14 |
---|---|
조명 셰이더 (0) | 2023.04.30 |
텍스쳐매핑 (0) | 2023.04.29 |
HLSL 원 그리기 (0) | 2023.04.29 |