Game Develop

[DirectX11] 라이팅 관련 잡다. 본문

ComputerGraphics/DirectX

[DirectX11] 라이팅 관련 잡다.

MaxLevel 2021. 2. 20. 09:26

직접광, 간접광이 있고 직접광은 2가지로 나뉜다.

 

============================================================================

직접광 -> 광원으로부터 직접 받는 빛

난반사(Diffuse) : 구 기준, 빛을 받았을 때 골고루 반사하는걸 뜻함. 즉 빨간빛을 비추면 골고루 빨간빛 반사.
                      보통 빛을 비추면 빛을 많이받는 부분, 많이 안받는 부분이 있다.
                      이 빛을 계산하는 식을 만든 사람 : Lambert(램버트)
                      cos값 이용하는 방법. (0~1).
                      표면의 법선(Normal) 이용. 
                       빛 방향벡터랑 구의 법선벡터를 내적하면 cos세타값이 나오기때문에 그걸로 값 결정. (0~1사이의 값)
                      계산하기위해 빛방향벡터 or 법선벡터의 방향을 바꿔서 계산해야하는데 보통 빛방향벡터 바꿈.       

          일단 단순히 난반사만 구현해서 적용할경우, 빛방향을 1, 즉 아예 안 비출때 그냥 다 새까만 검은색으로 나온다.
          이러면 너무 어색한데, 이럴 때 간접광을 구현한다.
 
정반사(Specular) :

                        빛이 어떤 물체에 반사되었을 때 입사각과 반사각이 같은 반사. 반사면이 평면에 가까울수록 정반사가 일어난다. 보통 사람눈으로 봤을 때 반사된빛은 하얗게 보인다. 컴퓨터그래픽스에서 하얀색은 rgb값이 1,1,1 이므로

빛을 비췄을 때 특정색을 더해줘야한다. 

이 더해주는 정도를 구하기위해 먼저 반사각을 구해줘야한다. 반사각을 구하는 공식은 따로있긴한데 hlsl내에 함수로 구현되어있다. 그거 사용하자.

 

============================================================================

간접광(Ambient) :

반사되는 빛.

디퓨즈만 적용한다음 어둡게 비추면 실제 세계와 다르게 너무 깜깜하다.

현실세계에서는 광원에서 나온 빛은 1차적으로 물체에 닿으면 다른 방향으로 튀면서 다른 물체를 밝히는데 사용된다.

이렇게 물체와 부딪혀 반사된 빛을 간접광(Indirect Lighting)이라고 한다.

이렇게 직접광과 간접광을 함께 반영하는 기법을 컴퓨터그래픽에서는 전역 조명(Global Illumination)이라고 한다.

 

구현방법 많음. 게임에서 완벽하게 구현하는건 거의 불가능.
보통 임의로 특정 색깔에 아주 얕은 %를 더해주는식으로 구현.



PixelInput VS(VertexInput input)
{

   PixelInput output;

 

output.pos = mul(input.pos, world);

output.pos = mul(output.pos, view);

output.p;os = mul(output.pos, projection);

 

float3 light = normalize(lightDirection); // 직접광 방향

float3 normal = normalize(mul(input.normal, (float3x3)world)); // 폴리곤 법선벡터 방향.

 

output.diffuse = saturate(dot(normal, -light)); // 내적하기위해서 두 벡터중 하나는 방향을 바꿔줘야하기때문에 -곱해줌.

 // saturate함수는 0~1의 범위로 값을 바꿔준다.
// 이 함수를 써야하는 이유는, 내적했을 때 cos90도를 넘어가면 값이 -로 넘어가게되는데
// 그러면 아래 픽셀셰이더에서 -값을 곱해버리기때문에 ambient(간접광)을 더해줘도
 // 그냥 새까맣게나온다. 그래서 saturate함수로 0~1사이로 바꿔줘야한다.

 

output.uv = input.uv;

 

return output;

}

 

Texture2D map : register(t0);
SamplerState samp : register(s0);

 

float4 PS(PixelInput input) : SV_Target
{

float4 color = map.Sample(samp, input.uv);

float4 ambient = color * 0.1f;

 

return color * input.diffuse + ambient; 

}