파티클과 조명 상호작용 기본 이해
Lit 셰이딩·그림자·이미시브 머티리얼·Light Renderer가 파티클과 주변 조명에 미치는 시각 효과와 비용을 비교합니다.
불꽃 입자를 아주 밝게 만들었는데도 옆의 벽은 전혀 밝아지지 않는 경우가 있습니다. 반대로 벽에 비친 조명이 너무 강해 프레임이 떨어지기도 합니다. 이런 혼란은 입자가 밝아 보이는 것, 입자가 바깥 조명을 받는 것, 입자가 주변 물체를 비추는 것이 서로 다른 기능이라는 점을 구분하지 않아서 생깁니다. 이 글에서는 세 가지 경로를 나누어 살펴보고, 그림자를 받는 것과 드리우는 것을 구분한 뒤, Light Renderer로 수명에 따라 서서히 꺼지는 빛을 만들어 봅니다.
빛을 받는 것, 밝게 보이는 것, 비추는 것
세 가지 경로는 각각 다른 설정으로 정합니다. 첫째는 셰이딩 모델이 Unlit인 경우로, Emissive Color로 색을 표현하며 표면의 직접 조명을 계산하지 않습니다. 스스로 빛나는 모습을 내기 쉽지만, 노출과 톤매핑, 안개 같은 것은 여전히 화면에 영향을 줄 수 있습니다.
둘째는 셰이딩 모델이 Default Lit인 경우로, Base Color와 Roughness, Normal 같은 입력으로 표면이 빛에 반응하게 합니다. 파편이나 먼지, 눈처럼 주변 환경에 자연스럽게 섞여야 하는 효과에 씁니다. 스프라이트에도 쓸 수 있지만, 반투명 머티리얼의 Lighting Mode와 렌더링 방식에 따라 지원 여부와 품질이 다릅니다.
셋째는 Light Renderer로, 입자의 위치에 조명을 만들어 주변의 표면을 비춥니다. 이것은 입자 표면의 셰이딩 모델과는 따로 정하는 것입니다. 그래서 Emissive나 블룸(Bloom)만 조절해 밝게 보이게 한 결과를 이 조명과 헷갈리지 않아야 합니다.
하나 더 구분할 것이 있습니다. Unlit과 Lit은 셰이딩 모델이고, Additive와 Translucent는 블렌드 모드입니다. 같은 종류의 선택지가 아니므로 각각 따로 정합니다.
NIAGARA · CH6-4
빛을 받는 표면·보이는 발광·주변 조명을 구분합니다
세 화살표는 서로 다른 역할입니다. 같은 효과에 조합할 수 있으며 Unlit/Lit 셰이딩 모델과 Additive/Translucent 블렌드 모드는 별도로 선택합니다.
조명을 받습니다
외부 조명에 반응하는 표면입니다. 반투명 Sprite는 Lighting Mode·렌더링 경로의 지원도 확인합니다.
밝은 픽셀로 보입니다
머티리얼의 발광 색을 화면에 표현합니다. 밝은 픽셀이나 Bloom이 주변 물체를 비추는 광원 생성과 같지는 않습니다.
주변을 직접 비춥니다
파티클 위치의 조명입니다. Color·Radius·활성 바인딩을 확인하고 주변 표면의 변화를 비교합니다.
비교할 결과를 나누어 확인합니다
파티클 자체의 색, 주변 Lit 벽·바닥의 직접 조명, 직접 비추지 않는 면의 간접광을 구분합니다. 이 그림은 GI·그림자 지원이나 특정 엔진 장면의 성공을 보장하지 않습니다.
Light Renderer의 Alpha Scales Brightness와 Sprite 재질의 Alpha→Opacity는 별도 소비 경로입니다. 수명 커브를 써도 각 바인딩을 맞춰야 하며 비용은 라이트 수·반경·지원되는 그림자 경로에서 측정합니다.
위 그림은 세 화살표로 서로 다른 역할을 보여 줍니다. 첫 번째 화살표는 외부 광원에서 Lit 입자 표면으로 이어지는 조명 받기로, 바깥 조명에 반응하는 표면입니다. 반투명 스프라이트라면 Lighting Mode와 렌더링 방식이 이를 지원하는지도 확인해야 합니다. 두 번째 화살표는 Unlit 머티리얼의 Emissive에서 화면의 입자 색으로 이어지는 밝은 픽셀로, 머티리얼의 발광 색을 화면에 그릴 뿐 주변 물체를 비추는 광원을 만들지는 않습니다. 세 번째 화살표는 Light Renderer에서 주변의 Lit 표면으로 이어지는 직접 조명으로, Color와 Radius, 활성 바인딩을 확인하고 주변 표면의 변화를 비교합니다.
그림 아래의 설명은 결과를 비교할 때 입자 자체의 색과, 주변 Lit 벽과 바닥의 직접 조명, 직접 비추지 않는 면의 간접광을 나누어 보라고 말합니다. 또 Light Renderer의 Alpha Scales Brightness와 스프라이트 머티리얼의 Alpha에서 Opacity로 가는 연결은 서로 다른 경로여서, 수명 커브를 쓰더라도 각 바인딩을 따로 맞춰야 합니다. 비용은 조명의 수와 반경, 지원되는 그림자 방식에서 측정합니다. 이 그림은 역할을 구분한 것이며, GI나 그림자의 지원, 특정 장면에서의 결과를 보장하지는 않습니다.
그림자를 받는 것과 드리우는 것
그림자도 두 가지를 구분해야 합니다. 하나는 입자의 표면에 그림자가 보이는 것이고, 다른 하나는 입자의 형태가 빛을 가려 다른 표면에 그림자를 드리우는 것입니다. Unlit이라고 해서 그림자를 드리우는 일이 모두 불가능한 것은 아니며, 불투명(Opaque)이나 마스크(Masked) 형태가 빛을 가리는 경우와 반투명의 그림자는 지원 조건이 다릅니다.
그림자를 시험할 때는 먼저 Mesh 입자 몇 개와 Opaque나 Masked 머티리얼, 그림자를 만드는 광원으로 작은 테스트 장면을 꾸밉니다. 다음으로 나이아가라 컴포넌트와 렌더러의 그림자 설정, 그리고 그림자 옵션과 성능 최적화에서 다룬 광원의 Cast Shadows를 확인합니다. 이 옵션이 어디에 있고 지원되는지는 엔진 버전과 렌더링 방식에 따라 다릅니다. 그런 다음 입자의 형태가 주변 바닥을 가려 그림자가 생기는지 확인합니다. 반투명 스프라이트는 같은 설정만으로 불투명 메시와 같은 그림자가 생긴다고 가정하지 말고, 그림자의 종류와 머티리얼의 지원을 따로 확인합니다.
그림자는 꼭 필요한 실루엣에만 쓰고, 입자 수나 화면 범위, 지속 시간을 늘리기 전에 비용을 비교합니다.
Light Renderer의 조절 값
Light Renderer에서 자주 조절하는 값은 다음과 같습니다.
Color Binding과Color Add: 입자의 색을 읽어 조명의 색으로 쓰고, 고정된 색 값을 더합니다. 밝기는 넘겨주는 RGB의 범위와 감쇠를 함께 보고 조절합니다.Radius Binding과Radius Scale: 입자마다의 반경과 그 배율로 조명이 닿는 범위를 정합니다. 기본 반경 바인딩은Particles.LightRadius입니다.Alpha Scales Brightness: 입자 색의 Alpha를 조명 밝기의 배율로 씁니다.Light Rendering Enabled Binding: 어떤 입자가 조명을 만들지 정합니다.
Point Light 컴포넌트의 속성이 모두 같은 이름으로 나이아가라 Light Renderer에도 있다고 가정하지 않습니다. 예를 들어 UE 5.8 API의 MegaLights Cast Shadows는 Allow MegaLights를 켰을 때만 쓰는 옵션입니다. 쓰는 버전에서 지원되는지 확인하며, 아래의 기본 실습은 그림자를 쓰지 않습니다.
수명에 따라 꺼지는 빛
NS_BasicSpawn을 복사해 Light Renderer를 더해 봅니다. 입자 자체가 보이도록 Sprite Renderer는 그대로 둡니다.
먼저 입자의 수를 줄이고 색을 정합니다. 조명은 비용이 크므로 Emitter Update의 Spawn Rate를 초당 5개 정도로 낮춥니다. Particle Spawn의 Initialize Particle에서 Lifetime을 1초, Color를 RGBA (1, 0.5, 0, 1)로 둡니다. 초기 속도를 주는 Add Velocity와 Particle Update의 Particle State, Solve Forces and Velocity가 있어 입자가 움직이고 수명이 다하면 사라지는지 확인합니다.
다음으로 Render 그룹에 Light Renderer를 추가합니다. Color Binding은 Particles.Color, Radius Binding은 Particles.LightRadius로 두고, Particle Spawn에 스크래치 패드 모듈을 하나 더해 Map Set으로 Particles.LightRadius에 Float 값 200(cm)을 씁니다. Radius Scale은 1, Color Add는 (0, 0, 0)에서 시작합니다. 그리고 Alpha Scales Brightness를 켭니다. 버전에 따라 있는 추가 그림자 경로는 이 실습에서 쓰지 않으며, Light Renderer의 값을 Point Light의 Intensity 1000 같은 설정으로 바꿔 설명하지 않습니다.
그다음 수명에 따라 알파가 줄게 합니다. Particle Update의 Scale Color에서 RGB 배율은 1로 두고, Alpha 배율에 Float From Curve를 연결합니다. 커브의 입력은 Particles.NormalizedAge, 키는 (0, 1)과 (1, 0), 보간은 Linear로 둡니다. 이 모듈은 Particle State 뒤에 두고, 다른 Color 모듈이 이 결과를 덮어쓰지 않게 합니다.
마지막으로 Lit 머티리얼을 쓰는 바닥과 벽이 있는 장면에서 재생합니다. 스프라이트의 머티리얼도 Particle Color의 Alpha를 읽게 해 두고, Light Renderer를 켰을 때와 껐을 때 주변 표면이 어떻게 다른지 비교합니다.
생긴 직후에는 밝고 수명이 끝나 갈수록 약해지는 조명이 예상되는 결과입니다. 빛이 잘 보이지 않으면 바인딩과 비추는 표면이 Lit인지, 거리와 노출을 먼저 확인합니다. 조명의 수와 반경, 그림자 방식이 비용을 크게 바꾸므로, 색의 밝기만 낮추는 것을 성능 최적화로 보지 않습니다.
하나의 알파가 두 곳에서 쓰인다
수명이 1초인 입자의 나이가 0.25초일 때를 따라가 봅니다. NormalizedAge는 0.25이고, (0, 1)에서 (1, 0)으로 내려가는 선형 커브의 값은 1 - 0.25 = 0.75입니다. 색을 쓰는 다른 Color 모듈이 없고 이 커브로 최종 Color의 Alpha가 0.75가 되었다면, Alpha Scales Brightness를 켠 Light Renderer는 조명 밝기에 0.75를 곱합니다. 스프라이트 머티리얼이 Alpha를 Opacity에도 연결했다면, 같은 알파 0.75를 그쪽의 별도 경로에서도 읽습니다.
| 나이 | NormalizedAge | 커브의 Alpha | Light Renderer 밝기 배율 | 스프라이트 Opacity |
|---|---|---|---|---|
| 0초 | 0 | 1 | 1 | 1 |
| 0.25초 | 0.25 | 0.75 | 0.75 | 0.75 |
| 0.5초 | 0.5 | 0.5 | 0.5 | 0.5 |
| 0.75초 | 0.75 | 0.25 | 0.25 | 0.25 |
이 표는 두 경로가 모두 알파를 읽도록 연결된 경우의 입력 값입니다. 최종 화면의 밝기를 재어 정확히 75%라고 확인했다는 뜻은 아닙니다.
정리
- 입자가 밝게 보이는 것은 Unlit과 Emissive가, 바깥 조명을 받는 것은 Lit 셰이딩이, 주변을 비추는 것은 Light Renderer가 정하는 서로 다른 경로입니다.
- 셰이딩 모델(Unlit, Lit)과 블렌드 모드(Additive, Translucent)는 서로 다른 선택이므로 각각 정합니다.
- 그림자를 받는 것과 드리우는 것은 다르며, 불투명이나 마스크 형태와 반투명 스프라이트는 그림자의 지원 조건이 다릅니다.
- Light Renderer는 Color와 Radius, Alpha Scales Brightness, Light Rendering Enabled 바인딩으로 조절하며, 기본 반경 바인딩은
Particles.LightRadius입니다. - 하나의 알파를 조명 밝기와 스프라이트 불투명도가 따로 읽으며, 알파를 낮춰도 조명의 수는 줄지 않습니다.
연습 문제
1. 밝기 배율만 끄면
본문의 입자에서 Alpha Scales Brightness만 끄고 스프라이트의 Alpha에서 Opacity로 가는 연결은 그대로 두었습니다. 알파 0.75가 두 출력에 주는 영향은 어떻게 달라질까요? 따로 Spawn Rate가 초당 5개, Lifetime이 1초인 효과를 충분히 오래 실행했고, 입자마다 조명을 하나씩 만들며 다른 제거나 활성 필터는 없다면 동시에 켜진 조명은 대략 몇 개일까요? 알파만 낮추면 조명의 수도 그만큼 줄었다고 판단해도 될까요?
해설 보기
Light Renderer는 이제 알파를 밝기 배율로 쓰지 않으므로 조명은 수명 내내 같은 밝기로 남습니다. 반면 스프라이트 머티리얼의 Opacity 경로는 여전히 0.75를 읽어 입자 자체는 그만큼 투명해집니다.
정상 상태에서 동시에 켜진 조명은 약 5 × 1 = 5개이며, 입자가 막 생기거나 사라지는 순간에는 조금 다를 수 있습니다. 알파 값을 낮추는 것은 Spawn Rate와 Lifetime, 활성 바인딩을 바꾸지 않으므로 조명의 수가 줄었다고 계산하지 않습니다. 비용을 줄이려면 실제 조명의 수와 반경, 활성 조건을 비교합니다.
2. 벽이 밝아지지 않는 불꽃
Unlit 머티리얼의 Emissive를 아주 크게 해서 불꽃이 눈부시게 빛나 보이는데, 바로 옆의 벽은 전혀 밝아지지 않습니다. 왜 그럴까요?
해설 보기
Emissive는 머티리얼의 발광 색을 화면의 픽셀로 그리는 것일 뿐, 주변 물체를 비추는 광원을 만들지 않습니다. 그래서 불꽃 자체는 밝게 보여도 벽에는 빛이 닿지 않습니다.
벽을 비추고 싶다면 Light Renderer를 더해 입자 위치에 조명을 만들고, 벽의 머티리얼이 Lit인지 확인합니다. 조명은 비용이 크므로 적은 수와 작은 반경으로 시작합니다.
3. 그림자가 생기지 않는 연기
반투명 스프라이트로 만든 연기가 바닥에 그림자를 드리우게 하고 싶어서 광원의 Cast Shadows를 켰는데, 그림자가 보이지 않습니다. 같은 설정으로 Opaque 메시 파편은 그림자가 생깁니다. 무엇을 확인해야 할까요?
해설 보기
불투명 메시와 반투명 스프라이트는 그림자를 드리우는 지원 조건이 다릅니다. 같은 광원 설정만으로 반투명 스프라이트도 불투명 메시와 같은 그림자를 드리운다고 가정할 수 없습니다.
나이아가라 컴포넌트와 렌더러의 그림자 설정을 확인하고, 쓰는 엔진 버전과 렌더링 방식에서 반투명 그림자를 어떤 종류로 지원하는지, 머티리얼이 그것을 지원하는지 따로 확인합니다. 연기 그림자가 꼭 필요한 실루엣인지도 비용과 함께 판단합니다.
Light Renderer의 속성과 바인딩은 Epic의 UNiagaraLightRendererProperties API 문서에서 확인할 수 있습니다.
다음 글 글로벌 일루미네이션과 파티클에서는 Lumen 같은 글로벌 일루미네이션이 입자의 빛과 어떻게 어울리는지, 그리고 그 지원 범위와 한계를 살펴봅니다.