1. 태양을 어떻게 구현할 것인가?
Point Light vs Directional Light
처음에는 실제 태양처럼 한점에서 모든 방향으로 퍼지는 Point Light로 태양을 구현하면 간단하게 끝나는 문제일 줄 알았다.
그래서 구현하기에 앞서 따른 사람들은 Point Light로 태양을 어떻게 구현하였는지 조금 찾아보았는데
Point Light로 태양을 나타내기에는 많은 문제가 있었다.
1. 평행광
태양은 지구와 같은 행성에서 볼 때 거리가 너무 멀기 때문에 빛이 거의 평행하게 들어옴.
그래서 Point Light보다는 Directional Light가 적합함.
2. 거리 기반 감쇄(Falloff) 문제
Point Light에서 빛의 세기는 거리에 비례에서 함께 줄어드는데 우주 배경에서 Point Light를 사용하기에는
행성과 행성, 태양과 행성 사이의 거리가 수만Km기 때문에 태양과 먼 거리의 행성은 감쇄비율 설정을 해도 빛이 도달하지 않음.
3. 성능문제
빛의 세기와 감쇄를 거리별로 계산해야 함, 모든 방향으로 퍼지는 빛을 개별적으로 계산, 범위 내 객체 수가 많을수록 부담이 큼
등과 같은 문제 때문에 성능 문제가 발생함
Directional Light로 태양 구현하기
이러한 이유 때문에 Point Light 보다는 Directional Light로 태양을 구현하였다.
Directional Light의 방향은 '나'와 '태양'의 위치를 계산해서
매 프레임마다 Directional Light 방향을 (나의 위치 - 태양 위치)로 업데이트 하도록 구현하였다.
게임에서는 어차피 '내'가 기준이라 태양빛의 방향을 내 기준으로 맞추기만 하면 끝날 줄 알았다.
void ASunGenerator::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
UpdateSunDirection();
}
void ASunGenerator::UpdateSunDirection()
{
if(!PlayerPawn || !SunLight)
return;
FVector PlayerLocation = PlayerPawn->GetActorLocation();
FVector SunPosition = GetActorLocation(); // 예제 태양 위치
FVector SunDirection = (PlayerLocation - SunPosition).GetSafeNormal();
FRotator TargetRotation = SunDirection.Rotation();
FRotator CurrentRotation = SunLight->GetActorRotation();
float InterpSpeed = 1.0f;
FRotator NewRotation = FMath::RInterpTo(CurrentRotation, TargetRotation, GetWorld()->GetDeltaSeconds(), InterpSpeed);
SunLight->SetActorRotation(NewRotation);
}
문제 1. 태양빛이 제대로 들어오지 않음
게임을 실행해보니까, 태양빛이 제대로 들어오지 않았다.
위 그림처럼 내 위치에 맞게 태양 -> 나 방향으로 Directional Light의 방향을 맞게 설정했고, 코드상에도 문제가 없었다.
곰곰히 생각해보니까, 빛이 실제로 태양에서 발생하는게 아니라 그냥 Directional Light이기 때문에 방향은 맞는데
태양에 가려서 도달하지 않는 것이었다.
GPT의 도움을 받아 태양이 Direcitonal Light에 가리지 않게 Light Channel을 변경해주니 빛이 나에게 잘 도달하였다.
문제 2. 다른 행성을 봤을 때 빛의 방향이 이상함
내 위치의 조명만 Okay면 될 줄 알았는데, 생각해보니까 내가 다른 행성을 볼 때의 경우도 처리해야 한다는 걸 깨달았다...
어떻게 해결해야 할지 또 고민했는데 답이 안나와서 Point Light로 그냥 태양을 표현해야하나 싶었는데
또 구글링하다가 좋은 아이디어를 얻게 되었다.
https://forums.unrealengine.com/t/solarsystem-like-lighting-omni-directional-light/307533/4
Solarsystem-like Lighting || Omni-directional light
Oh, now i see the problem. My suggestion works for larger-multiple systems but it isnt sufficient for the situation you describe. For non-player objects that are visible to the player you could try adding custom lighting to the materials(by using a materia
forums.unrealengine.com
한마디로 정의하면 행성 표면에서 태양 방향을 계산하여 Material의 Emissive Color를 조절하면 각 행성이 태양 위치에 따라 다르게 조명을 받는 것처럼 보이게 만들 수 있다.
그래서 위 방법을 적용해서 태양 위치에 따라 행성의 Emissive Color를 업데이트 하는 코드를 추가하였다.
1. 매 프레임마다 MPC의 SunDirection값을 업데이트
// 매 프레임마다 SunDirection 값 업데이트
if (MPCInstance)
{
MPCInstance->SetVectorParameterValue(FName("SunDirection"), SunDirection);
}
2. MPC의 SunDirection값과, Normal Vector값의 내적으로 반사되는 빛의 세기 계산
3. 반사되는 빛의 세기 * Base Color * 빛 번짐값을 Emissive Color로 설정
Material에서 색상값을 처리해서 표현하기 때문에 그림자 같은 효과는 발생하지 않아 성능에도 부담이 없고
어차피 먼 곳에서 행성을 보기 때문에 큰 영향은 없을 것 같다.
게임을 구현하면서 발생하는 문제을 해결하는 아이디어를 배운다는게 참 재밌는 것 같다.
3. 추가적인 처리
태양빛이 안들어오는 부분이 너무 어두워서 Sky Light를 추가해 어두운 부분도 약간은 보일 수 있게 개선.
완성
이렇게 태양과 조명을 구현해 보았다.
그림과 동일하게 행성과 태양을 배치하고 한 컷 찍어봤는데 잘 나와서 기분이 좋다.
'작심삼일 > The Cosmic Robot' 카테고리의 다른 글
반짝반짝 작은 (0) | 2025.02.23 |
---|---|
설날 프로젝트 - 공전과 자전 (0) | 2025.01.31 |
설날 프로젝트 - 행성과 중력 (0) | 2025.01.27 |
설날 프로젝트 - 절차적 행성 생성 (0) | 2025.01.27 |
설날 프로젝트 - 목표 (0) | 2025.01.23 |