DirectX

47. Light, Material_Emissive

devRiripong 2024. 2. 14.
반응형

외곽선을 그릴 때 사용하는 립라이트, Emissive에 대해서 알아본다.

 

가장 쉽고 단순한 방법으로 만들어 본다.

 

1. 12. Lighting_Emissive.fx와 15. EmissiveDemo클래스를 생성하고, 각각 EmissiveDemo::Init과 Main에서 세팅하기 

 

하던대로 11. Lighting_Specular.fx를 복제해서 이름을 12. Lighting_Emissive로 한다. Client/Shader/Week2 필터에 넣는다.

 

탐색기에서 14. SpecularDemo 클래스를 복제해서 이름을 15. EmissiveDemo라고 한다. Client/Game/Week2에 넣는다.

코드를 EmissiveDemo에 맞게 수정한다.

EmissiveDemo.cpp에서

#include "15. EmissiveDemo.h"
_shader = make_shared<Shader>(L"12. Lighting_Emissive.fx");

 

Main.cpp 에서도

#include "15. EmissiveDemo.h"
desc.app = make_shared<EmissiveDemo>(); // 실행 단위

 

쉐이더부터 작업을 해서 살펴본다.

 

2. Lighting_Emissive.fx 쉐이더 작성하기

Lighting_Emissive.fx에 가서

float3 LightDir; 
float4 LightSpecular; // 색상

빛과 관련이 좀 없기 때문에 이 둘은 삭제한다.

 

float4 MaterialEmissive;

Material 남겨둔다.

 

Texture2D DiffuseMap;

삭제한다.

 

// Emissive
// 외각선 구할 때 사용
// (림라이트)
float4 PS(MeshOutput input) : SV_TARGET
{
    float3 cameraPosition = -V._41_42_43; 
    float3 E = normalize(cameraPosition - input.worldPosition); 
    
    float value = saturate(dot(E, input.normal));   // Specular에서는 R고 E를 dot 해줬지만, 여기선 E와 normal을 해준다.
    float emissive = 1.0f - value;    // 1은 0, 0은 1로 바꿔준다.
    
    // min, max, x
    emissive = smoothstep(0.0f, 1.0f, emissive); // emissive가 0보다 작으면 0, 1보다 크면 1을 반환
    
    float4 color = MaterialEmissive * emissive; 
    
    return color;
}

이렇게 해주고 결과물을 보고 분석을 해본다.

 

3. EmissiveDemo::Update에서 MaterialEmissive의 값을 세팅하기 

EmissiveDemo::Update에서

light가 필요 없으니

//
Vec4 light{ 1.f}; 
_shader->GetVector("LightSpecular")->SetFloatVector((float*)&light);

Vec3 lightDir{ 1.f, -1.f, 0.f }; 
lightDir.Normalize(); 
_shader->GetVector("LightDir")->SetFloatVector((float*)&lightDir);

를 삭제한다.

 

void EmissiveDemo::Update()
{
	_camera->Update(); 
	RENDER->Update(); 

	{
		Vec4 materialEmissive(1.f, 0.f, 0.f, 1.f); 
		_shader->GetVector("MaterialEmissive")->SetFloatVector((float*)&materialEmissive);
		_obj->Update();

	}

	{
		Vec4 materialEmissive(0.f, 1.f, 0.f, 1.f);
		_shader->GetVector("MaterialSpecular")->SetFloatVector((float*)&materialEmissive);
		_obj2->Update();
	}
}

이렇게

12. Lighting_Emissive.fx의 float4 MaterialEmissive;의 값을 세팅한다.

 

꼭 이렇게 해야 하는 건 아니고, 빛에 따라가지고, 빛의 얼마만큼을 받는지를 해도 안 될 건 아니다.

 

이렇게 material에 따라 설정을 했다.

 

실행을 해보면

큐브는 normal이 잘 안보이니 그렇다 치고,

 

외각 부분만 빨강으로 뜨고, 나머지는 검정으로 뜨는 것을 볼 수 있다.

 

4. emissive 값을  제곱 해줘서 테스트 해보기 

저금 더 특수 효과 강하게 주기 위해

PS에서

emissive = pow(emissive, 2);

이렇게 2승을 하고 살펴 보면

 

빨강이 더 얇아지는 걸 볼 수 있다.

 

5. PS 분석하기 

왜 이렇게 되는지 궁금하다. 식을 보면서 거꾸로 유추해 볼 수 있다.

// Emissive
// 외각선 구할 때 사용
// (림라이트)
float4 PS(MeshOutput input) : SV_TARGET
{
    float3 cameraPosition = -V._41_42_43; 
    float3 E = normalize(cameraPosition - input.worldPosition); 
    
    float value = saturate(dot(E, input.normal));   // Specular에서는 R고 E를 dot 해줬지만, 여기선 E와 normal을 해준다.
    float emissive = 1.0f - value;    // 1은 0, 0은 1로 바꿔준다.
    
    // min, max, x
    emissive = smoothstep(0.0f, 1.0f, emissive); // emissive가 0보다 작으면 0, 1보다 크면 1을 반환
    emissive = pow(emissive, 2); 
    float4 color = MaterialEmissive * emissive; 
    
    return color;
}

카메라 위치에 따라서 Eye 벡터를 구한 것 까진 동일 한데

Eye 벡터에 input.normal을 내적해서 뭔가를 시도했다는 걸 볼 수 있다.

물체를 normal과 일치하게 직각으로 바라볼 수록 일반적으로 보여야 하는 것인데,

그게 아니라 normal과 90도가 될 수록 좋은 상황이 된 것이다.

즉 normal 벡터를 가진 물체의 면이 안보이게 되는 걸 찾고 싶게 된 것이다.

일반적인 경우는 0으로 밀어 놓고, normal과 Eye과 90에 이르는 부분을 찾아서 거기만 거꾸로 원하는 색으로 칠해 주자가 아이디어이다.

지금까진 normal과 같은 방향인게 좋았는데 이제는 90도를 이루거나 멀리 떨어져 있는 애들만 찾아서 다른 색상을 입혀 보자가 컨셉이다.

그래서 원래 구한 값에서 1-value를 해서 반대 방향으로 해버린 것이다. 0이었으면 1이 되고 1이었으면 0이 되는 거꾸로 뒤집어진 것을 이용해서 최종 색상을 구해줬다.

emissive라는 값은 바라 보는 방향과 normal 벡터가 90도가 되면 될수록 좋은 것이다 보니까 외곽선을 이렇게 구해줄 수 있는 거다.

지금까지 했던 것과 반대되는 개념으로 구해준 상황이다.

 

Eye방향과 normal 방향이 멀어질 수록 색을 칠해줬다가 결론이 된다.

 

필요에 따라 LIghtEmissive를 받아서 하는 건 옵션이 된다.

 

나머지 애들 Ambient, DIffuse, Specular에 비해 사용 빈도가 떨어진다.

 

이제 지금까지 했던 것들을 합쳐서 한번에 만들어 것이다.

반응형

'DirectX' 카테고리의 다른 글

49. Light, Material_Material  (0) 2024.02.16
48. Light, Material_Light 통합  (0) 2024.02.15
46. Light, Material_Specular  (0) 2024.02.13
45. Light, Material_Diffuse  (0) 2024.02.13
44. Light, Material_Ambient  (0) 2024.02.13

댓글