본문 바로가기
기본 쉐이더

빛에 관한 공식

by Raypop 2010. 9. 16.

1. 확산 반사광(Diffuse Light)

램버트의 코사인 법칙을 수식으로 나타내면, 빛의 강도를 Id, 입사각을 θ, 물체의 반사계수를(물체의색) Kd라 하면, 물체 표면의색 I는 다음과 같다.

I = Id * kd * cosθ = Id * Kd * (N*L)

(단, cosθ가 음수인 경우(법선과 광원이 반대로 향하고 있는 경우)에는 값을 0으로 합니다. N은 물체 표면의 법선벡터, L은 광원이 있는 방향을 가르키는 강원벡터이며, Id,Kd는 색 성분으로 벡터며, 그 곱셈은 색성분 간의 곱셈이다)

 

2. 환경광(Ambient Light)

환경광을 수식으로 나타내면 빛의 강도를 Ia, 물체의 반사 계수를(물체 색)Ka라고 하면, 물체 표면의 색 I 는 다음과 같다.

I = Ia * Ka

 

램버튼의 코사인 법칙에 의한 확산 조명과 환경광에 의한 라이팅을 램버트 조명 모델이라고 부릅니다.

I = Ia * Ka + Id * Kd * (N*L)

      환경광        확산 반사광

 

이것을 쉐이더에서 사용하는 공식으로 고치게 되면

I = Ia * Ka + Id * Kd * max(0,dot(N, L))

으로 나타낼수 있다. 여기서 max를 사용함으로써 라이팅이 음의 값이 되었을때 최소값인 0으로 설정해주기 위함이다.

 

※ 최적화

- Id * Kd 로 색의 계수를 계산했지만 이계산은 정점마다 값이 바뀔 일이 없기 때문에 미리 계산해두는것이 효과적이다.

 

- 환경광과 확산 반사광은 색의 강도가 다를뿐 색감이 다를 경우는 많지 않으므로 다음과 같이 색을 일괄 식으로 사용하는 것이 효율이 좋다.

I = color * (0.3 + 1.0 * (N*L))

 

여기서 color 는 일반적인 오브젝트의 색이며 0.3 이나 1.0은 환경광과 확산반사광의 강도입니다. 0.3 값을 큰값으로 하면 환경광이 강해지고, 1.0 값을 작게 하면 확산 반사광이 작아지는 이미지가 됩니다.

 

- 내적 계산을 줄이기 위한 방법. 법선백터를 4차원 벡터로 취급한다. DirectX 에서는 입력 레지스터의 차원을 원래 데이터 보다 크게 하면, 크게 한 성분에는 자동적으로 1이 들어갑니다. 즉, 법선 벡터는 (Nx,Ny,Nz,1) 값이 입력 데이터로 들어 옵니다. 여기서 N과 L의 내적을 계산하면

(Nx,Ny,Nz,1) * (Lx,Ly,Lz,Lw) = Nx * Lx + Ny * Ly + Nz * Lz + Lw

 

따라서 Lw를 환경광의 강도라고 생각하면 3차원 벡터의 내적과 정수 Lw의 합이라고 생각할 수 있다.

환경광 강도의 비유을 amb로 해서 코사인 법칙의 음수 부분을 0으로 제한하는 식으로 만들면 다음과 같다.

amb + max(0,N*L) = max(amb,N*L) + amb

 

max의 두번째 인자는 4차원 벡터로 법선 벡터와 광원 벡터의 내적이다.

이를 쉐이더 프로그래밍으로 수정하게 되면

 

float4 vColor; // 광원 * 메쉬 색

float amb = L.w;

Out.Color = vColor * max(amb,dot(Normal,L));

 

3. 퐁 반영 반사광(Phong Specularity)

 

퐁은 시선이 물체에 반사되었을 때의 반사 벡터 R을 구해서 반사 벡터가 광원 벡터(물체에서 광원을 향하는)L과 가까우면 강한빛, R과 L이 멀면 약한 빛이 되도록 수식화했습니다.

I = Ia * Ka + Id * Kd * (N*L) + Is * Ks * cosⁿθ

  = Ia * Ka + Id * Kd * (N*L) + Is * Ks * (L*R)ⁿ

       환경광        확산 반사광        블린-퐁의 반영 반사광

 

n은 반사 지수라고 부르는데,

만약 n이 무한대라면 L*R 이 1.0일때만 1.0 이며, 1.0 이하라면 0이 됩니다. 즉, 반사벡터와 광원벡터 방향이 같은 부분에만 비추어집니다.(ex 거울)

반사지수가 무한대가 아닐 때는, 반사 벡터가 광원 벡터에서 조금 벗어난 곳도 밝아집니다. 즉, 하이라이트가 희미하게 확대됩니다. 하이라이트는 반사 지수에 의해 크게 바뀌게 되는데 반사 지수가 10 이하의 작은 값일때는, 넓은 범위에 걸쳐서 반사 하이라이트가 적용되지만 반사 지수가 100 정도로 커지면 반짝이는 표면이 되어 하이라이트가 점의 형태로 됩니다.

 

반사 벡터 R 은

R = -E + 2(N*E)N

으로 E는 시선벡터로, 물체에서 카메라를 보는 방향입니다. 단, 퐁의 반사 모델에서도 내적 값이 음수가 되는 경우에는 빛이 닿지 않는 것으로 해석하여 강도를 0으로 계산합니다.

 

4. 블린-퐁의 반영 반사광(Blinn-Phong Specularity)

블린-퐁의 반영 반사광은 하프벡터(H)와 법선 벡터 내적(N)의 제곱으로 계산합니다.

I = Ia * Ka + Id * Kd * (N*L) + Is * Ks + cosⁿθ

  = Ia * Ka + Id * Kd * (N*L) + Is * Ks + (N*H)ⁿ

       환경광        확산 반사광        블린-퐁의 반영 반사광

 

5. 픽셀 단위 반영 반사

법선 벡터 등의 값은 정점 셰이더를 사용할 경우 입력변수로 자유롭게 다룰 수 있지만, 픽셀 셰이더에는 그러한 변수가 없기 때문에 직접 픽셀 셰이더에 넘겨주지 않으면 안 됩니다. 이럴 때 자주 이용되는 방법이 정점 셰이더의 출력 값으로 넘겨주는 데이터에 포함시키는 것입니다. 특히, 텍스처 좌표는 적당한 벡터로 사용할 수 있으므로 정점 셰이더로 만든 데이터를 픽셀 셰이더에 넘겨주는 데 자주 이용 됩니다.

 

struct VS_OUTPUT

{

  float4 Pos : POSITION;

  float4 Color : COLOR0;

  float4 N : TEXCOORD0;

  float4 Eye : TEXCOORD1;

}


'기본 쉐이더' 카테고리의 다른 글

Half Lambert 의 원리와 공식  (0) 2010.12.09
스터디 - Fx(UV맵을 활용한 효과)  (0) 2010.12.04
스터디 - 스페큘러맵  (0) 2010.11.28
스터디 - 기본 노멀맵  (0) 2010.11.16
쉐이더에 사용되는 기본 계산식  (0) 2010.09.13