본문 바로가기
DirectX 12/Camera & Lighting

[DirectX12 - Camera & Lighting] Chapter 03. Lighting

by song.ift 2023. 6. 15.

GitHub : https://github.com/developeSHG/DirectX12-Camera_Lighting/commits/03.Lighting

 

GitHub - developeSHG/DirectX12-Camera_Lighting: DirectX12 - Camera & Lighting

DirectX12 - Camera & Lighting. Contribute to developeSHG/DirectX12-Camera_Lighting development by creating an account on GitHub.

github.com

 

결과물

 

 


 

 

물체마다 자신의 RGB 값이 있는데, 거기다 각각 곱해지는 성분자체를 구하는 것이 Lighting의 개념.
예시) R(1) * 0.5
      G(0) * 0.5
      B(0) * 0.1



diffuse - 난반사
ambient - 환경
specular - 정반사

 

 

diffuse는 물체가 맞닥드리는 각도를 얘기한다. 각 픽셀별로 평면에 대한 노말벡터가 있을텐데, 빛이랑 정확하게 일치하느냐?
빛의 반대방향벡터와 노말벡터 그 사이각이 0도, 즉 완전히 선이 일치할수록 빛을 받는 세기가 쌜것이고, 반대로 비스듬히 받을수록 당연히 세기는 약해지니
어두워져 보이는 개념이다. 즉 픽셀에서의 평면 노말벡터와 빛을 받는 방향의 반대 노말벡터와의 코사인 각도 값이 중요하다.

 

 

ambient는 기초 생활비처럼 기초수급비용처럼 아무 빛을 못받았다해도, 기본적으로 조금이나마 반사반사 되어서
받는 그 색상 빛을 얘기한다. 어둡게어둡게 조금씩 물체가 보이긴 한다.
(테이블 밑에 물체를 놨다고 해서 아예 안보이는 건 아닌 현상을 생각하면 쉽다)

 

 

specular 성분은 빛이 튕겨져 나왔을 떄, 그 반사각 벡터가 우리 눈에 반짝이면서 보인다 라는게 개념이였다.
diffuse처럼 빛의 방향벡터에 의해 직각으로 반사되는 벡터와 카메라의 룩벡터와 내적해서 사이각이 0도일수록 
더 빛의 세기가 강하게 보이는 게 동일하다. 즉 코사인 각도 값이 중요하다.

 

결과론적으로 보면 모두 다 빛이라고 할 수 있지만,
diffuse는 빛을 얼마나 받느냐? 물체의 색상을 표현
ambient는 기본 보이는 diffault 값. 
specular는 실질적으로 바라보는 사람의 눈의 각도와 튕겨져나오는 각도에 의해 결정. 발광, 빛이 우리눈에 번쩍이는 가를 표현.

 


 

위는 빛의 속성이였고
빛의 종류는 directional, pointlight, spotlight 가 있다.

위는 directional의 특징이엿지만, 다른 빛들도 완전히 다르진 않다.
pointlight는 횟불을 생각하면 된다. 
directional은 한 방향으로 쏘지만, pointlight는 일정 특정범위 안에서 빛의 좌표가 각각 다른 방향벡터로 쏴서 세기를 계산한다.
(횟불은 당연히 모든 공간을 비추지 않으니)

spotlight는 손전등을 생각하면 된다 했다.
이것도 pointlight처럼 특정 유효범위만 비춘다.
계산법은 spotlight의 pos에서 하나의 픽셀의 위치를 향한 룩벡터 a와
spot의 룩벡터를 내적한다. 그 벡터 둘은 단위벡터이기 때문에 코사인 각도 값 즉, distance(음수,양수)를 쉽게 구할 수 있다.
만약 spot가 지정한 유효범위 d가 distance보다 작냐(받음) 크냐(안받음) 를 조건을 판단해서 빛을 받게 안받게 해줄수있다.
distance가 음수면 아예 뒤에 있음.
위에건 1차 검수였고, spot는 손전등처럼 일정 각도가 있는지 판단해야 하기 때문에 2차 검수가 필요하다.
spotlight의 최대 시야각안에 있는지 판단하려면 픽쉘의 위치와 빛의 방향벡터의 각도를 구해서 비교하면 된다.
각도를 구하는 법은 픽쉘 위치와 빛의 방향벡터를 내적해서 코사인 값을 구한다. (둘다 단위벡터이기 때문에 코사인 값 나옴)
그 다음, 코사인값을 다시 아크 코사인을 해버리면 값이 아닌 각도가 나오게 된다.
그래서 그 구한 각도가 최대 시야각보다 작으면 안에 있다고 판단한다.

(벡터의 내적과 외적은 주로 이런 빛을 이용한 세기를 구할 때, 많이 이용될 수 도있으니 참고)

pointlight와 spotlight는 그라데이션이 들어간다. 밝다가 갑자기 꺼지면 이상하니까.
근데 point는 좀 그라데이션이 많이 들어가지만, spot는 좀 더 갑자기 자른게 더 자연스럽게 들어간다.

directional은 빛의 룩벡터만 알면 되고,
pointlight는 광원의 위치(각각 다른 방향벡터로 빛을 쏘니까), 최대범위(유효범위, distance)

이로써 알 수 있는건 빛의 종류마다 각각 다른 데이터를 추가로 넣어줘야 한다는 걸 알수있다.

 

 


 

 

#3

쉐이더 코드에서는
빛 연산을 해야하는 좌표들이 필요한데
꼭 필요한건 픽셀좌표와 픽셀의 노말좌표다.
이 둘을 알아야 반사각이니 빛의 세기니 다 계산할 수 있는 것.

근데 모든 연산을 좌표계는 어디일까?
당연히 하나 좌표는 월드로 하고, 다른 좌표는 뷰로 하는게 말이 안된다.
월드? 뷰? 행렬?
세 개중에서 어딘가에서 해야한다. 정답은 없다. 프로그래머가 정하면된다.
근데 일반적으로 월드나 뷰에서 한다. 좌표계를 하나로 통일해야 한다.
월드에서 많이 하지만, 뷰에서도 할 수 있다. 뷰에서 하면 좋은 건 카메라의 좌표를 또 쉐이더에 넘길 필요가 없다는 것.
뷰 좌표계에서는 애당초 카메라 좌표가 0 0 0 원점이기 때문에, 굳이 카메라 좌표를 넘겨주지 않아도 된다.
그래서 코드에선 뷰 좌표계를 기준으로 했고, viewPos와 viewNoraml에 g_matMV를 곱해서 결과를 만든다.



-VS_MAIN
이 함수 즉, 버텍스 쉐이더에서 구해준 부분은 노란색 삼각형이라고 치면
각 버텍스를 정해준 부분이고,

-PS_MAIN
버텍스 쉐이더 후 레스터라이즈 단계에서 보간을 해준 후, 버텍스 사이 보간된 픽셀 단위로 연산을 하고 있는 부분이다.

댓글