본문 바로가기
Shader

ShaderGraph 에서 Additional Light 받아오기

by 대마왕J 2024. 8. 31.

https://chulin28ho.tistory.com/559/#comment18330696

 

ShaderGraph 에서 LightDirection 가져오기

ShaderGraph를 만지다보면, lightDirecion 노드가 없다는걸 당황하게 됩니다. Shader 를 조금 배우다 보면 바로 나오는 NdotL을 구현할 수 없다는데 당황하게 되는데요, 뭐.. 요샌 그게 추세이니까 -_- ; 그래

chulin28ho.tistory.com

이 글에서 허허님이 그러면 Additional Light 는 어떻게 받냐고 하셔서.. 
허허허 이분이 허허... 

책을 사세요! 라고 말해드리고 싶지만

애석하게도 저 책에서도 Additional Light 부분은 설명하지 않았습니다. 왜냐면 책 페이지가 너무 늘어나서였어요 크흑. 지금도 두꺼운데 .. 

그래서 뭐 질문도 들어온 김에.. 여기서 간단하게 만들어 드립니다. 

사전지식

먼저 알아야 할 사전지식이 하나 있는데요,  이미 아시는 것 처럼 Directional Light 하나는 기본적으로 Main Light 연산으로 처리됩니다만, Directional Light 가 추가가 되거나 Point, Spot Light 등의 라이트가 추가되면 그 라이트는 'Additional Light' 라고 불리면서 완전히 따로 연산되게 됩니다. 
즉 Main Light + Additional Light 인거죠. 
왜 이렇게 처리를 해놨냐면.. Additional Light 는 URP에서 8개까지의 갯수제한이 있고 플렛폼이나 옵션에 따라 이 수치가 변할 수도 있어서 그렇습니다. 역시 Forward Renderer는 라이트갯수에 민감한 법이지요. 요즘엔 Forward+ 까지 나와서 이 양상이 더 복잡해지기도 하고.. 여하간 

일단 하고 싶은 말은 , Point Light 를 추가하려면 Additional Light 연산을 추가해야 한다는 것입니다. 

Additional Light 를 Shader Graph 에서 받아봅시다. 

그래요 받아봅시다. 

일단 Custom Function 노드를 하나 만듭니다. 여기서 Additional Light 를 받을거예요 

Input 과 Output 에 아래와 같이 해 줍시다. 
Input 은 Vector3 의 WorldPosition 과 WorldNormal을 받고 
Output은 Diffuse 를 Vector3 로 만듭시다. 여기에 최종 결과가 들어갈 거예요 

음...이전에 Main Light 정보를 받을때는 Color 와 Direction을 출력해서 그걸로 NdotL 연산을 했는데요, 
Additional Light 는 그렇게 못합니다. 왜냐고요? 최대 8개까지라고 그랬잖아요? 즉 유동적으로 각 라이트의 갯수별로 NdotL 계산 횟수를 바꿔가면서 해줘야 하는데, 노드로는 그게 불가능해서 코드로 다 해버리는 거예요. 

자 입출력이 됐으면 Type은 String으로 바꾸고 (File 로 하는게 사실 더 편한데 여기서는 간단하게 할거니까) 
Name은 AdditionalLights 로 해 줍니다. 

그리고 아래 칸에다가 이렇게 써주면 돼요 

float3 AdditionalLightColor = 0;
#ifndef SHADERGRAPH_PREVIEW
    uint pixelLightCount = GetAdditionalLightsCount();

    LIGHT_LOOP_BEGIN(pixelLightCount)
        Light light = GetAdditionalLight(lightIndex, WorldPosition);
        float3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
        AdditionalLightColor += LightingLambert(attenuatedLightColor, light.direction, WorldNormal);
    LIGHT_LOOP_END
#endif
Diffuse = AdditionalLightColor;

그럼 아래와 같은 모양이 되겠죠 

이러면 끝입니다. 아주 간단하게 설명하자면  
uint pixelLightCount = GetAdditionalLightsCount(); 에서 Additional Light 갯수를 받아오고, 
그 갯수만큼 
LIGHT_LOOP_BEGIN(pixelLightCount)

LIGHT_LOOP_END
사이를 라이트 갯수만큼 돌면서 중복으로 계산하는 것입니다. 

그래서 이 노드에 알맞은 정보를 입력해 주면.. 

 

이렇게 되고 

이제 Additional Light 를 받을 수 있게 됩니다. 이거랑 Main Light 결과를 곱해주면 되는 것이지요
(여전히 뭔가 디테일한 기능들은 빠졌지만 ... ) 

여기까지입니다. 

 

반응형

댓글