본문 바로가기
툰렌더링 공부

언리얼 엔진 뜯어보기 #2

by IX. 2023. 3. 24.

3.24

셰이더 모델은 추가했다. 하지만 더 재미있는 걸 하기 전에, 먼저 리로드방법에 대해 알아야 한다.

C++파일이야 어쩔 수 없지만, 수정이 잦은 파일을 고칠 때마다 엔진을 재시동하는 건 비효율적이다.

 

그렇다면 먼저 확인을 위해 최종 Output이 어디에 붙어있는지 파악해야 한다.

일단 DeferredLightPixelShaders.usf 에서 그럴싸해 보이는 값을 수정해보자.

// OutColor.rgb = AtmosphericTransmittance * Radiance.xyz * Attenuation * LocalCoverage * GetExposure();	
OutColor.rgb = float3(1, 0, 0);
OutColor.a = LocalCoverage;

 

안된다.(...) 이게 아닌가

그건 그렇고, 어쨌거나 예쁜 LIT셰이더

공식문서를 보니 Ctrl+Shift+.로 셰이더를 재컴파일 할 수 있다고 써 있다.

이거라면 시간을 좀 더 단축할 수 있다!

그렇다고 시간이 안걸리는 건 아니지만...

일단 이것 저것 값을 고쳐보자.

코드처럼 최종 아웃풋을 빨갛게 표현하고 싶다.

 

하지만 어떤 값을 변경해도 변화가 없다.

루멘이야 그렇다쳐도 Unlit은 변해야 할텐데!?

 

내일 다시 도전해보자.

실패하면 될 때까지!

 

3.27

아웃컬러를 조절하는 부분은 BasePassPixelShader.usf에 있다.

여기서 컬러를 계산한 후, 이를 빛누적기(LightAccumulator)에 넘겨준다.

이를 넘겨주기 전에 Color를 빨간색으로 강제로 맞춰주었다.

언릿은 예상대로 붉은색이 나온다. 하지만 여전히 Lit은 형태를 띈다.

난 최종색깔 = RGB라고 처리된 부분을 찾고 있었는데, 언리얼은 그보단 좀 더 복잡한 로직을 사용하는 것 같다.

하지만 코드만 길었지, 절반정도는 Strata라는 머티리얼 합성 시스템에 사용되는 로직들이다. 

이 Strata여전히 실험기능이라고 한다.언리얼을 4.0에 만났다면 조금 더 쉬웠을까.(하지만 루멘도 없었겠지..)

 

Chat GPT는 언리얼4 시절의 정보를 담고 있지만, 그래도 도움은 된다.

고장내보자.

	Out.MRT[0] = half4(0, 1, 0, 1);
	Out.MRT[1] = half4(1, 0, 0, 1);
	Out.MRT[2] = half4(0, 0, 1, 1);
	Out.MRT[3] = half4(1, 0, 0, 1);
	Out.MRT[4] = half4(1, 1, 0, 1);

3.28

건강검진으로 인해 이틀휴가

사렬줘...

 

3.30

BasePassPixelShader.usf를 수정할 경우 머티리얼을 적용시켜 놓고 Apply를 누르면 5분걸릴 셰이더 컴파일이 5초만에 끝난다. 전역에 적용되지는 않지만, 셰이더 개발엔 더 없이 좋은 처리방법이다. 역시 매뉴얼을 잘 읽어야 한다. 

 

3.31

원하는 거의 모든 내용은 BasePassPixelShader.usf에 모두 기술되어 있다. 예상과는 다르게 MRT배열은 0번만 중요하고, 나머지는 모션블러등에 사용된다. mainPS()에서 사용되는 Out구조체는 생각보다 단순했다.

struct FPixelShaderOut
{
	// [0..7], only usable if PIXELSHADEROUTPUT_MRT0, PIXELSHADEROUTPUT_MRT1, ... is 1
	float4 MRT[8];
	
	// Explicit uint output specific to strata.
	uint StrataOutput[3];

	// Pixel Shader OutCoverage, only usable if PIXELSHADEROUTPUT_COVERAGE is 1
	uint Coverage;

	// Pixel Shader OutDepth
	float Depth;
};

마참내! 원하던 걸 찾아냈다. 이 코드는 간접광과 AO를 합성해서 돌려주는 것 같다. 물론 예상대로 돌아갈지는 좀 더 확인이 필요하다.

 

DiffuseColor += (DiffuseIndirectLighting * DiffuseColorForIndirect + SubsurfaceIndirectLighting * SubsurfaceColor) * AOMultiBounce( GBuffer.BaseColor, ShadingOcclusion.DiffOcclusion );

그리고 좀 더 다양한 연산을 거쳐서 그 값을 Color에 넘겨준다.

#if !POST_PROCESS_SUBSURFACE && !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
 	// For skin we need to keep them separate. We also keep them separate for thin translucent.
	// Otherwise just add them together.
	Color += DiffuseColor;
#endif

#if !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
	Color += Emissive;
#endif

그리고 그 컬러는 빛 연산을 거쳐

LightAccumulator_Add(LightAccumulator, Color, 0, 1.0f, false);

MRT 0번배열에 저장된다.

Out.MRT[0] = RETURN_COLOR(LightAccumulator_GetResult(LightAccumulator));

하지만 이전에 했듯이 MRT[0]을 단색으로 맞춰도 어쩐지 더 칠해지는 색들이 있다.

이것에 대해선 좀 더 나중에 조사해보자.