반응형

Shading Model을 추가했으나, Type을 제외하고는 아무것도 설정되어 있지 않기 때문에, 무언가 작동이 되도록 해보도록 한다.

 

이전에 발생한 ensure 문제부터 해결해보자.

 

// HLSLMaterialTranslator.cpp

void FHLSLMaterialTranslator::GetMaterialEnvironment(EShaderPlatform InPlatform, FShaderCompilerEnvironment& OutEnvironment)
{
	~~ ... ~~
    
    ensure(NumSetMaterials != 0);
    
    ~~ ... ~~
}

NumSetMaterials가 0 으로 표시되면서 ensure가 발생한다.

문제가 되는 ensure의 윗부분을 보면, Shiding Model에 따라 NumSetMaterial을 증가하는 코드가 들어있다.

마찬가지로 Custom Shading Model을 추가해준다.

// HLSLMaterialTranslator.cpp

void FHLSLMaterialTranslator::GetMaterialEnvironment(EShaderPlatform InPlatform, FShaderCompilerEnvironment& OutEnvironment)
{
	~~ ... ~~
    
    if (ShadingModels.HasShadingModel(MSM_ThinTranslucent))
    {
        OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT"), TEXT("1"));
        NumSetMaterials++;

        bMaterialRequestsDualSourceBlending = true;
    }
    if (ShadingModels.HasShadingModel(MSM_DR_CellShading))
    {
        OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_DR_CELL_SHADING"), TEXT("1"));
        NumSetMaterials++;
    }

    if (ShadingModels.HasShadingModel(MSM_SingleLayerWater) && FDataDrivenShaderPlatformInfo::GetRequiresDisableForwardLocalLights(Platform))
    {
        OutEnvironment.SetDefine(TEXT("DISABLE_FORWARD_LOCAL_LIGHTS"), TEXT("1"));
    }
    
    ~~ ... ~~
}

 

기본 EMaterialShadingModel 타입을 비교하는 조건문 밑의 조건들은, Shading Model이 아닌 다른 조건들도 체크하기 때문에, Shading Model들과 함께 위치해주었다.

 

MaterialHLSLEmitter.cpp 파일에도 동일한 코드가 있다.

마찬가지로 GetMaterialEnvironment 함수 내에, 동일한 로직에 추가해준다.

 

미리 추가해두었다면 다음으로 넘어가지만, 이전의 접은글을 확인하지 않았다면, GBuffer 슬롯을 위한 변수 정의를 추가한다.

// ShaderMaterial.h

struct FShaderMaterialPropertyDefines
{
	~~ ... ~~
    
	uint8 MATERIAL_COMPUTE_FOG_PER_PIXEL : 1;
	uint8 MATERIAL_SHADINGMODEL_UNLIT : 1;

	uint8 MATERIAL_SHADINGMODEL_DEFAULT_LIT : 1;
	uint8 MATERIAL_SHADINGMODEL_SUBSURFACE : 1;
	uint8 MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN : 1;
	uint8 MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE : 1;
	uint8 MATERIAL_SHADINGMODEL_CLEAR_COAT : 1;
	uint8 MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE : 1;
	uint8 MATERIAL_SHADINGMODEL_HAIR : 1;
	uint8 MATERIAL_SHADINGMODEL_CLOTH : 1;
	uint8 MATERIAL_SHADINGMODEL_EYE : 1;
	uint8 MATERIAL_SHADINGMODEL_SINGLELAYERWATER : 1;
	uint8 SINGLE_LAYER_WATER_DF_SHADOW_ENABLED : 1;
	uint8 MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT : 1;
	uint8 MATERIAL_SHADINGMODEL_DR_CELL_SHADING : 1;

	~~ ... ~~
};

 

HLSL 코드에 대한 Custom Data를 추가하는 과정이다.

// ShaderGenerationUtil.cpp

template<typename EnvironmentType>
void ApplyFetchEnvironmentInternal(FShaderMaterialPropertyDefines& SrcDefines, const EnvironmentType& Environment)
{
	~~ ... ~~

	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_DEFAULT_LIT);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_SUBSURFACE);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_CLEAR_COAT);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_HAIR);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_CLOTH);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_EYE);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_SINGLELAYERWATER);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT);
	FETCH_COMPILE_BOOL(MATERIAL_SHADINGMODEL_DR_CELL_SHADING);

	~~ ... ~~
}

ApplyFetchEnvironmentInternal 함수는 구성 설정에 따른 오버로딩 함수가 많으므로, FShaderMaterialPropertyDefines 파라미터를 확인 후 수정하여야 한다.

 

GBuffer 슬롯 변수를 설정하여쓰면, Slot을 사용하기 위한 정의가 필요하다.

// ShaderGenerationUtil.cpp

static void DetermineUsedMaterialSlots(
	bool Slots[],
	const FShaderMaterialDerivedDefines& Dst,
	const FShaderMaterialPropertyDefines& Mat,
	const FShaderLightmapPropertyDefines& Lightmap,
	const FShaderGlobalDefines& SrcGlobal,
	const FShaderCompilerDefines& Compiler,
	ERHIFeatureLevel::Type FEATURE_LEVEL)
{
	~~ ... ~~

	if (Mat.MATERIAL_SHADINGMODEL_SINGLELAYERWATER)
	{
		// single layer water uses standard slots
		SetStandardGBufferSlots(Slots, bWriteEmissive, bHasTangent, bHasVelocity, bHasStaticLighting, bIsStrataMaterial);
		if (Mat.SINGLE_LAYER_WATER_SEPARATED_MAIN_LIGHT)
		{
			Slots[GBS_SeparatedMainDirLight] = true;
		}
	}

	// doesn't write to GBuffer
	if (Mat.MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT)
	{
	}

	if (Mat.MATERIAL_SHADINGMODEL_DR_CELL_SHADING)
	{
		SetStandardGBufferSlots(Slots, bWriteEmissive, bHasTangent, bHasVelocity, bHasStaticLighting, bIsStrataMaterial);
		Slots[GBS_CustomData] = bUseCustomData;
	}
}
// ShaderGenerationUtil.cpp

static void SetSlotsForShadingModelType(bool Slots[], EMaterialShadingModel ShadingModel, bool bMergeCustom)
{
	~~ ... ~~
	case MSM_SingleLayerWater:
		SetSharedGBufferSlots(Slots);
		Slots[GBS_SeparatedMainDirLight] = true;
		break;
	case MSM_ThinTranslucent:
		// thin translucent doesn't write to the GBuffer
		break;
	case MSM_DR_CellShading:
		SetSharedGBufferSlots(Slots);
		if (bMergeCustom)
		{
			Slots[GBS_CustomData] = true;
		}
		else
		{
			Slots[GBS_SubsurfaceColor] = true;
			Slots[GBS_Opacity] = true;
		}
		break;
	}
}

Shading Model & GBuffer에 대한 설정이 끝났다.

이제 Shading Model을 사용하기 위한 구현으로 넘어가자.

반응형

+ Recent posts