[DX11] 조명 (Ambient, Diffuse, Specular)

LeeTaes·2024년 1월 9일
0

DirectX

목록 보기
9/9

조명

  • DirectX의 조명 모델에서 광원이 만들어 내는 빛은 아래의 3가지 요소로 구성되어 있습니다.
  • 아래 3가지 요소를 적절하게 합쳐 자연스러운 빛 효과를 낼 수 있습니다.
  1. Ambient Light (환경광, 주변광 조명)
    • 환경광은 다른 표면에 반사되어 전반적인 장면을 밝게 하는 빛을 모델링합니다.
    • 반사된 빛을 비교적 저렴하고 간단하게 구현하는 방법입니다.
  1. Diffuse Light (난반사광, 분산광 조명, 분산 조명)
    • 난반사광의 방정식에는 빛의 방향과 표면의 형태만을 고려하면 되며, 난반사광은 광원에서 발산되는 가장 일반적인 빛입니다.
  1. Specular Light (정반사광, 반영광 조명, 반영 조명)
    • 정반사광은 특정한 방향으로 진행하며, 표면에 닿으면 한 방향으로 강하게 반사하여 특정한 각도에서만 관찰할 수 있습니다.
    • 정반사광은 반짝이는 표면에 빛이 반사되는 효과를 모델링하는 데 이용됩니다.

Material 간단 설명

  • Material은 3D 그래픽스에서 물체의 표면 특성을 정의하는 데 사용되는 개념입니다.
  • 빛의 상호 작용, 색상, 반사 등을 제어하여 물체가 어떻게 렌더링 되는지를 결정합니다.
  • 앞으로 나오는 Material은 간단히 물체에 적용될(흡수하는) 색상 정도로 생각해주시면 되겠습니다.

1. Ambient Light (환경광, 주변광 조명)

  • Ambient는 환경광으로 광원이 불분명한 빛을 의미합니다.
  • 즉, 이곳 저곳 반사되어 돌아다니다 최종적으로 물체에 맞는 빛입니다.
  • 특징 : 일정한 밝기와 색으로 표현
  • Ambient Light는 쉽게 말하면 모든 곳에서 존재하는 빛입니다.
  • 광원이 존재한다고 가정했을 경우 실제 세상에서는 위와 같이 빛의 반사가 발생합니다.
  • 즉, 광원의 반대편이라고 빛이 전혀 영향을 주지 않는 것은 아니라는 이야기입니다.
  • 이와 같이 Ambient Light는 모든 영역에 일정한 양의 빛을 전달해주는 역할이라고 생각할 수 있습니다.

Ambient Light의 공식

float4 color = LightAmbient * MaterialAmbient;
  • 빛의 세기와 Material에서 설정한 Ambient의 값을 곱해주면 완성됩니다.

2. Diffuse Light (난반사광, 분산광 조명, 분산 조명)

  • Diffuse Light는 특정한 방향으로 진행하며, 표면에 닿으면 모든 방향으로 동일하게 반사됩니다.
  • 간단히 생각했을 때의 가장 일반적인 빛 형태라고 생각할 수 있습니다.
  • 특징 : 각도에 따라 밝기가 다르다.

  • 위와 같이 노란색 광원에서 빛이 들어왔을 때 정확히 90도인 부분은 밝게 빛나고, 0도까지 내려가며 점점 희미해지다 반대편으로는 빛이 전달되지 않는 현상을 나타낼 때 사용합니다.
  • 즉, 물체의 표면에서 빛이 분산되어 눈으로 들어오는 빛 이라고 생각할 수 있습니다.

Diffuse Light 공식

	// 공용 셰이더에서 설정한 SamplerState를 적용시켜줍니다.
	float4 color = DiffuseMap.Sample(LinearSampler, input.uv);

	// 출력될 색상을 조명의 연산에 따라 추가 연산해줍니다.
	float value = dot(-LightDir, input.normal);
	color = color * value * LightDiffuse * MaterialDiffuse;


3. Specular Light (정반사광, 반영광 조명, 반영 조명)

  • Specular Light는 Diffuse Light와 비슷하지만 반짝임 효과를 내기 위해 사용합니다.
  • 물체의 Normal벡터에 반사된 빛 벡터와 물체에서 눈(Camera)으로 가는 벡터를 구해 둘 사이의 값에 따라 반짝임(눈부심 효과)을 조정합니다.
  • 특징 : 한 방향으로 완전히 반사되는 빛

Specular Light 공식

// 반사된 빛의 벡터를 구해줍니다.
// 1. 내장 함수 이용하기 reflect()
// 2. 직접 구하기
//float3 R = reflect(LightDir, input.normal);

// * dot(LightDir, input.normal)와 input.normal을 곱해준 이유
//   -> dot(LightDir, input.normal)의 결과는 스칼라 값 -> 벡터로 변경해주기 위함
float3 R = LightDir - (2 * input.normal * dot(LightDir, input.normal));

// 카메라의 위치를 구해줍니다.
// * View 행렬의 4-1,2,3 인자를 꺼내 -부호를 붙여준 것이 카메라의 위치입니다.
float3 cameraPosition = -V._41_42_43;

// 물체에서 카메라까지 가는 방향 벡터를 구해줍니다.
// * 월드상의 (카메라 위치 - 물체 위치)의 정규화 
float3 E = normalize(cameraPosition - input.worldPosition);

// 구한 방향벡터들을 내적해 값을 추출합니다. (R, E)
// * 항상 0 ~ 1 사이의 값을 남기기 위해 saturate() 함수 사용
// * saturate() : 0 ~ 1 사이를 유지시켜주는 함수입니다. 0이하로 내려가면 0, 1이상으로 넘어가면 1로 유지시켜줍니다.
float value = saturate(dot(R, E));

// Specular 값으로 연산해 넣어줍니다.
// * 연산이 필요한 이유 : 0 ~ 1 사이의 값을 사용하면 너무 넓은 범위가 설정됩니다.
// * 0 ~ 1 사이의 값이므로 제곱을 통해 값을 줄여 범위를 줄여줄 수 있습니다.
float specular = pow(value, 10);

// 최종적으로 반환하기 위한 색상을 구해줍니다.
// * 다른 빛들은 텍스처와 상관있게 표현했지만, Specular는 눈부심을 적용하기 위해 주로 사용하므로, 텍스처의 샘플링 없이 진행합니다.
float4 color = LightSpecular * MaterialSpecular * specular;

조명 통합

  • 어떤 물체가 받을 여러 종류의 빛의 총 합은 간단히 덧셈을 통해 구해주면 됩니다.
    ex) return ambientColor + diffuseColor + specularColor;
profile
클라이언트 프로그래머 지망생

0개의 댓글