예제 #1
0
FShadowMap2D* FShadowMap2D::AllocateInstancedShadowMap(UInstancedStaticMeshComponent* Component, TArray<TMap<ULightComponent*, TUniquePtr<FShadowMapData2D>>> InstancedShadowMapData,
	const FBoxSphereBounds& Bounds, ELightMapPaddingType InPaddingType, EShadowMapFlags InShadowmapFlags)
{
#if WITH_EDITOR
	check(InstancedShadowMapData.Num() > 0);

	// Verify all instance shadowmaps are the same size, and build complete list of shadow lights
	int32 SizeX = -1;
	int32 SizeY = -1;
	TSet<ULightComponent*> AllLights;
	for (auto& ShadowMapData : InstancedShadowMapData)
	{
		for (const auto& ShadowDataPair : ShadowMapData)
		{
			if (SizeX == -1)
			{
				SizeX = ShadowDataPair.Value->GetSizeX();
				SizeY = ShadowDataPair.Value->GetSizeY();
			}
			else
			{
				check(ShadowDataPair.Value->GetSizeX() == SizeX);
				check(ShadowDataPair.Value->GetSizeY() == SizeY);
			}
			AllLights.Add(ShadowDataPair.Key);
		}
	}

	check(SizeX != -1 && SizeY != -1); // No valid shadowmaps

	TArray<FGuid> LightGuids;
	LightGuids.Reserve(AllLights.Num());
	for (ULightComponent* Light : AllLights)
	{
		LightGuids.Add(Light->LightGuid);
	}

	// Unify all the shadow map data to contain the same lights in the same order
	for (auto& ShadowMapData : InstancedShadowMapData)
	{
		for (ULightComponent* Light : AllLights)
		{
			if (!ShadowMapData.Contains(Light))
			{
				ShadowMapData.Add(Light, MakeUnique<FQuantizedShadowSignedDistanceFieldData2D>(SizeX, SizeY));
			}
		}
	}

	FShadowMapAllocationGroup AllocationGroup;
	AllocationGroup.TextureOuter = Component->GetOutermost();
	AllocationGroup.ShadowmapFlags = InShadowmapFlags;
	AllocationGroup.Bounds = Bounds;
	if (!GAllowStreamingLightmaps)
	{
		AllocationGroup.ShadowmapFlags = EShadowMapFlags(AllocationGroup.ShadowmapFlags & ~SMF_Streamed);
	}

	FShadowMap2D* BaseShadowmap = nullptr;

	for (int32 InstanceIndex = 0; InstanceIndex < InstancedShadowMapData.Num(); ++InstanceIndex)
	{
		auto& ShadowMapData = InstancedShadowMapData[InstanceIndex];
		check(ShadowMapData.Num() > 0);

		// Create a new shadow-map.
		FShadowMap2D* ShadowMap = new FShadowMap2D(LightGuids);

		if (InstanceIndex == 0)
		{
			BaseShadowmap = ShadowMap;
		}

		// Add a pending allocation for this shadow-map.
		TUniquePtr<FShadowMapAllocation> Allocation = MakeUnique<FShadowMapAllocation>();
		Allocation->PaddingType = InPaddingType;
		Allocation->ShadowMap = ShadowMap;
		Allocation->TotalSizeX = SizeX;
		Allocation->TotalSizeY = SizeY;
		Allocation->MappedRect = FIntRect(0, 0, SizeX, SizeY);
		Allocation->Primitive = Component;
		Allocation->InstanceIndex = InstanceIndex;

		for (auto& ShadowDataPair : ShadowMapData)
		{
			auto& RawData = ShadowDataPair.Value;
			auto& DistanceFieldShadowData = Allocation->ShadowMapData.Add(ShadowDataPair.Key, TArray<FQuantizedSignedDistanceFieldShadowSample>());

			switch (RawData->GetType())
			{
			case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA:
			case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA_QUANTIZED:
				// If the data is already quantized, this will just copy the data
				RawData->Quantize(DistanceFieldShadowData);
				break;
			default:
				check(0);
			}

			RawData.Reset();

			// Track the size of pending light-maps.
			PendingShadowMapSize += Allocation->TotalSizeX * Allocation->TotalSizeY;
		}

		// Assumes bAlignByFour
		AllocationGroup.TotalTexels += ((Allocation->MappedRect.Width() + 3) & ~3) * ((Allocation->MappedRect.Height() + 3) & ~3);

		AllocationGroup.Allocations.Add(MoveTemp(Allocation));
	}

	PendingShadowMaps.Add(MoveTemp(AllocationGroup));

	return BaseShadowmap;
#else
	return nullptr;
#endif
}
예제 #2
0
FShadowMap2D* FShadowMap2D::AllocateShadowMap(
	UObject* Outer, 
	const TMap<ULightComponent*,FShadowMapData2D*>& ShadowMapData,
	const FBoxSphereBounds& Bounds, 
	ELightMapPaddingType InPaddingType,
	EShadowMapFlags InShadowmapFlags)
{
#if WITH_EDITOR

	check(ShadowMapData.Num() > 0);

	// Create a new shadow-map.
	FShadowMap2D* ShadowMap = new FShadowMap2D(ShadowMapData);

	int32 SizeX = -1;
	int32 SizeY = -1;
	int32 LightIndex = 0;

	for (TMap<ULightComponent*, FShadowMapData2D*>::TConstIterator It(ShadowMapData); It; ++It)
	{
		if (LightIndex == 0)
		{
			SizeX = It.Value()->GetSizeX();
			SizeY = It.Value()->GetSizeY();
		}
		else
		{
			check(SizeX == It.Value()->GetSizeX() && SizeY == It.Value()->GetSizeY());
		}

		LightIndex++;
	}

	check(SizeX != -1 && SizeY != -1);

	// Add a pending allocation for this shadow-map.
	FShadowMapAllocation* Allocation = new(PendingShadowMaps) FShadowMapAllocation;
	Allocation->ShadowMap		= ShadowMap;
	Allocation->TextureOuter	= Outer->GetOutermost();
	Allocation->TotalSizeX		= SizeX;
	Allocation->TotalSizeY		= SizeY;
	Allocation->MappedRect		= FIntRect( 0, 0, SizeX, SizeY );
	Allocation->PaddingType		= InPaddingType;
	Allocation->Bounds			= Bounds;
	Allocation->ShadowmapFlags	= InShadowmapFlags;

	if ( !GAllowStreamingLightmaps )
	{
		Allocation->ShadowmapFlags = EShadowMapFlags( Allocation->ShadowmapFlags & ~SMF_Streamed );
	}

	for (TMap<ULightComponent*, FShadowMapData2D*>::TConstIterator It(ShadowMapData); It; ++It)
	{
		const FShadowMapData2D* RawData = It.Value();
		TArray<FQuantizedSignedDistanceFieldShadowSample>& DistanceFieldShadowData = Allocation->ShadowMapData.Add(It.Key(), TArray<FQuantizedSignedDistanceFieldShadowSample>());

		switch (RawData->GetType())
		{
		case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA:
		case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA_QUANTIZED:
			// If the data is already quantized, this will just copy the data
			RawData->Quantize(DistanceFieldShadowData);
			break;
		default:
			check(0);
		}

		delete RawData;

		// Track the size of pending light-maps.
		PendingShadowMapSize += Allocation->TotalSizeX * Allocation->TotalSizeY;
	}

	return ShadowMap;
#else
	return NULL;
#endif 
}
예제 #3
0
FShadowMap2D* FShadowMap2D::AllocateShadowMap(
	UObject* Outer, 
	const TMap<ULightComponent*,FShadowMapData2D*>& ShadowMapData,
	const FBoxSphereBounds& Bounds, 
	ELightMapPaddingType InPaddingType,
	EShadowMapFlags InShadowmapFlags)
{
#if WITH_EDITOR
	check(ShadowMapData.Num() > 0);

	FShadowMapAllocationGroup AllocationGroup;
	AllocationGroup.TextureOuter = Outer->GetOutermost();
	AllocationGroup.ShadowmapFlags = InShadowmapFlags;
	AllocationGroup.Bounds = Bounds;
	if (!GAllowStreamingLightmaps)
	{
		AllocationGroup.ShadowmapFlags = EShadowMapFlags(AllocationGroup.ShadowmapFlags & ~SMF_Streamed);
	}

	// Create a new shadow-map.
	FShadowMap2D* ShadowMap = new FShadowMap2D(ShadowMapData);

	// Calculate Shadowmap size
	int32 SizeX = -1;
	int32 SizeY = -1;
	int32 LightIndex = 0;
	for (const auto& ShadowDataPair : ShadowMapData)
	{
		if (LightIndex == 0)
		{
			SizeX = ShadowDataPair.Value->GetSizeX();
			SizeY = ShadowDataPair.Value->GetSizeY();
		}
		else
		{
			check(SizeX == ShadowDataPair.Value->GetSizeX() && SizeY == ShadowDataPair.Value->GetSizeY());
		}

		LightIndex++;
	}
	check(SizeX != -1 && SizeY != -1);

	// Add a pending allocation for this shadow-map.
	TUniquePtr<FShadowMapAllocation> Allocation = MakeUnique<FShadowMapAllocation>();
	Allocation->PaddingType = InPaddingType;
	Allocation->ShadowMap = ShadowMap;
	Allocation->TotalSizeX = SizeX;
	Allocation->TotalSizeY = SizeY;
	Allocation->MappedRect = FIntRect(0, 0, SizeX, SizeY);
	Allocation->PaddingType = InPaddingType;

	for (const auto& ShadowDataPair : ShadowMapData)
	{
		const FShadowMapData2D* RawData = ShadowDataPair.Value;
		TArray<FQuantizedSignedDistanceFieldShadowSample>& DistanceFieldShadowData = Allocation->ShadowMapData.Add(ShadowDataPair.Key, TArray<FQuantizedSignedDistanceFieldShadowSample>());

		switch (RawData->GetType())
		{
		case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA:
		case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA_QUANTIZED:
			// If the data is already quantized, this will just copy the data
			RawData->Quantize(DistanceFieldShadowData);
			break;
		default:
			check(0);
		}

		delete RawData;

		// Track the size of pending light-maps.
		PendingShadowMapSize += Allocation->TotalSizeX * Allocation->TotalSizeY;
	}

	// Assumes bAlignByFour
	AllocationGroup.TotalTexels += ((Allocation->MappedRect.Width() + 3) & ~3) * ((Allocation->MappedRect.Height() + 3) & ~3);

	AllocationGroup.Allocations.Add(MoveTemp(Allocation));

	PendingShadowMaps.Add(MoveTemp(AllocationGroup));

	return ShadowMap;
#else
	return nullptr;
#endif
}