LumenSceneData 初始化 [1]

前置信息:

灯光从World到Scene的流程。

UE4 Lights UWorld to FScene [1]_spawnactor failed because of collision at the spaw_sh15285118586的博客-CSDN博客

 mesh从world到Scene流程,与灯光类似

void UStaticMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext* Context)
{
	LLM_SCOPE(ELLMTag::StaticMesh);
	Super::CreateRenderState_Concurrent(Context);
}

void UPrimitiveComponent::CreateRenderState_Concurrent(FRegisterComponentContext* Context)
{
	// Make sure cached cull distance is up-to-date if its zero and we have an LD cull distance
	if( CachedMaxDrawDistance == 0.f && LDMaxDrawDistance > 0.f )
	{
		bool bNeverCull = bNeverDistanceCull || GetLODParentPrimitive();
		CachedMaxDrawDistance = bNeverCull ? 0.f : LDMaxDrawDistance;
	}

	Super::CreateRenderState_Concurrent(Context);

	UpdateBounds();

	// If the primitive isn't hidden and the detail mode setting allows it, add it to the scene.
	if (ShouldComponentAddToScene())
	{
		if (Context != nullptr)
		{
			Context->AddPrimitive(this);
		}
		else
		{
			GetWorld()->Scene->AddPrimitive(this);
		}
	}

	// Components are either registered as static or dynamic in the streaming manager.
	// Static components are registered in batches the first frame the level becomes visible (or incrementally each frame when loaded but not yet visible). 
	// The level static streaming data is never updated after this, and gets reused whenever the level becomes visible again (after being hidden).
	// Dynamic components, on the other hand, are updated whenever their render states change.
	// The following logic handles all cases where static components should fallback on the dynamic path.
	// It is based on a design where each component must either have bHandledByStreamingManagerAsDynamic or bAttachedToStreamingManagerAsStatic set.
	// If this is not the case, then the component has never been handled before.
	// The bIgnoreStreamingManagerUpdate flag is used to prevent handling component that are already in the update list or that don't have streaming data.
	if (!bIgnoreStreamingManagerUpdate && (Mobility != EComponentMobility::Static || bHandledByStreamingManagerAsDynamic || (!bAttachedToStreamingManagerAsStatic && OwnerLevelHasRegisteredStaticComponentsInStreamingManager(GetOwner()))))
	{
		FStreamingManagerCollection* Collection = IStreamingManager::Get_Concurrent();
		if (Collection)
		{
			Collection->NotifyPrimitiveUpdated_Concurrent(this);
		}
	}
}
void FScene::AddPrimitive(UPrimitiveComponent* Primitive)
{
	SCOPE_CYCLE_COUNTER(STAT_AddScenePrimitiveGT);
	SCOPED_NAMED_EVENT(FScene_AddPrimitive, FColor::Green);

	checkf(!Primitive->IsUnreachable(), TEXT("%s"), *Primitive->GetFullName());

	const float WorldTime = GetWorld()->GetTimeSeconds();
	// Save the world transform for next time the primitive is added to the scene
	float DeltaTime = WorldTime - Primitive->LastSubmitTime;
	if ( DeltaTime < -0.0001f || Primitive->LastSubmitTime < 0.0001f )
	{
		// Time was reset?
		Primitive->LastSubmitTime = WorldTime;
	}
	else if ( DeltaTime > 0.0001f )
	{
		// First call for the new frame?
		Primitive->LastSubmitTime = WorldTime;
	}

	checkf(!Primitive->SceneProxy, TEXT("Primitive has already been added to the scene!"));

	// Create the primitive's scene proxy.
	FPrimitiveSceneProxy* PrimitiveSceneProxy = Primitive->CreateSceneProxy();
	Primitive->SceneProxy = PrimitiveSceneProxy;
	if(!PrimitiveSceneProxy)
	{
		// Primitives which don't have a proxy are irrelevant to the scene manager.
		return;
	}

	// Create the primitive scene info.
	FPrimitiveSceneInfo* PrimitiveSceneInfo = new FPrimitiveSceneInfo(Primitive, this);
	PrimitiveSceneProxy->PrimitiveSceneInfo = PrimitiveSceneInfo;

	// Cache the primitives initial transform.
	FMatrix RenderMatrix = Primitive->GetRenderMatrix();
	FVector AttachmentRootPosition = Primitive->GetActorPositionForRenderer();

	struct FCreateRenderThreadParameters
	{
		FPrimitiveSceneProxy* PrimitiveSceneProxy;
		FMatrix RenderMatrix;
		FBoxSphereBounds WorldBounds;
		FVector AttachmentRootPosition;
		FBoxSphereBounds LocalBounds;
	};
	FCreateRenderThreadParameters Params =
	{
		PrimitiveSceneProxy,
		RenderMatrix,
		Primitive->Bounds,
		AttachmentRootPosition,
		Primitive->GetLocalBounds()
	};

	// Help track down primitive with bad bounds way before the it gets to the Renderer
	ensureMsgf(!Primitive->Bounds.ContainsNaN(),
			TEXT("Nans found on Bounds for Primitive %s: Origin %s, BoxExtent %s, SphereRadius %f"), *Primitive->GetName(), *Primitive->Bounds.Origin.ToString(), *Primitive->Bounds.BoxExtent.ToString(), Primitive->Bounds.SphereRadius);

	INC_DWORD_STAT_BY( STAT_GameToRendererMallocTotal, PrimitiveSceneProxy->GetMemoryFootprint() + PrimitiveSceneInfo->GetMemoryFootprint() );

	// Verify the primitive is valid
	VerifyProperPIEScene(Primitive, World);

	// Increment the attachment counter, the primitive is about to be attached to the scene.
	Primitive->AttachmentCounter.Increment();

	// Create any RenderThreadResources required and send a command to the rendering thread to add the primitive to the scene.
	FScene* Scene = this;

	// If this primitive has a simulated previous transform, ensure that the velocity data for the scene representation is correct
	TOptional<FTransform> PreviousTransform = FMotionVectorSimulation::Get().GetPreviousTransform(Primitive);

	ENQUEUE_RENDER_COMMAND(AddPrimitiveCommand)(
		[Params = MoveTemp(Params), Scene, PrimitiveSceneInfo, PreviousTransform = MoveTemp(PreviousTransform)](FRHICommandListImmediate& RHICmdList)
		{
			FPrimitiveSceneProxy* SceneProxy = Params.PrimitiveSceneProxy;
			FScopeCycleCounter Context(SceneProxy->GetStatId());
			SceneProxy->SetTransform(Params.RenderMatrix, Params.WorldBounds, Params.LocalBounds, Params.AttachmentRootPosition);

			// Create any RenderThreadResources required.
			SceneProxy->CreateRenderThreadResources();

			Scene->AddPrimitiveSceneInfo_RenderThread(PrimitiveSceneInfo, PreviousTransform);
		});

}

 AddedPrimitiveSceneInfos 会在后面创建LumenSceneData用到。

void FScene::AddPrimitiveSceneInfo_RenderThread(FPrimitiveSceneInfo* PrimitiveSceneInfo, const TOptional<FTransform>& PreviousTransform)
{
	check(IsInRenderingThread());
	check(PrimitiveSceneInfo->PackedIndex == INDEX_NONE);
	check(AddedPrimitiveSceneInfos.Find(PrimitiveSceneInfo) == nullptr);
	AddedPrimitiveSceneInfos.FindOrAdd(PrimitiveSceneInfo);
	if (PreviousTransform.IsSet())
	{
		OverridenPreviousTransforms.Update(PrimitiveSceneInfo, PreviousTransform.GetValue().ToMatrixWithScale());
	}
}

LumenSceneData创建流程

Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp

Scene->UpdateAllPrimitiveSceneInfos(GraphBuilder, true);
void FScene::UpdateAllPrimitiveSceneInfos(FRDGBuilder& GraphBuilder, bool bAsyncCreateLPIs)
{
    TArray<FPrimitiveSceneInfo*> AddedLocalPrimitiveSceneInfos;
	AddedLocalPrimitiveSceneInfos.Reserve(AddedPrimitiveSceneInfos.Num());
	for (FPrimitiveSceneInfo* SceneInfo : AddedPrimitiveSceneInfos)
	{
		AddedLocalPrimitiveSceneInfos.Add(SceneInfo);
	}

	AddedLocalPrimitiveSceneInfos.Sort(FPrimitiveArraySortKey());
    
    while (AddedLocalPrimitiveSceneInfos.Num())
	{
		int32 StartIndex = AddedLocalPrimitiveSceneInfos.Num() - 1;
        for (int AddIndex = StartIndex; AddIndex < AddedLocalPrimitiveSceneInfos.Num(); AddIndex++)
		{
				FPrimitiveSceneInfo* PrimitiveSceneInfo = AddedLocalPrimitiveSceneInfos[AddIndex];
				int32 PrimitiveIndex = PrimitiveSceneInfo->PackedIndex;
				FPrimitiveSceneProxy* SceneProxy = PrimitiveSceneInfo->Proxy;

				if (ShouldPrimitiveOutputVelocity(SceneProxy, GetShaderPlatform()))
				{
					PrimitiveSceneInfo->bRegisteredWithVelocityData = true;
					// We must register the initial LocalToWorld with the velocity state. 
					// In the case of a moving component with MarkRenderStateDirty() called every frame, UpdateTransform will never happen.
					VelocityData.UpdateTransform(PrimitiveSceneInfo, PrimitiveTransforms[PrimitiveIndex], PrimitiveTransforms[PrimitiveIndex]);
				}

				DistanceFieldSceneData.AddPrimitive(PrimitiveSceneInfo);
				LumenAddPrimitive(PrimitiveSceneInfo);
         }

    }
}

// Add function is a member of FScene, because it needs to add the primitive to all FLumenSceneData at once
void FScene::LumenAddPrimitive(FPrimitiveSceneInfo* InPrimitive)
{
	LLM_SCOPE_BYTAG(Lumen);

	if (DefaultLumenSceneData->bTrackAllPrimitives)
	{
		const FPrimitiveSceneProxy* Proxy = InPrimitive->Proxy;
		bool bTrackPrimitveForLumenScene = TrackPrimitiveForLumenScene(Proxy);

		for (FLumenSceneDataIterator LumenSceneData = GetLumenSceneDataIterator(); LumenSceneData; ++LumenSceneData)
		{
			// We copy this flag over when creating per-view lumen scene data, validate that it's still the same
			check(LumenSceneData->bTrackAllPrimitives == DefaultLumenSceneData->bTrackAllPrimitives);

			LumenSceneData->PrimitivesToUpdateMeshCards.Add(InPrimitive->GetIndex());

			if (bTrackPrimitveForLumenScene)
			{
				ensure(!LumenSceneData->PendingAddOperations.Contains(InPrimitive));
				ensure(!LumenSceneData->PendingUpdateOperations.Contains(InPrimitive));
				LumenSceneData->PendingAddOperations.Add(InPrimitive);
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值