游戏线程(GameThread)
编辑器中(EWorldType::Editor,模拟运行或编辑状态)
bool GetObserverView(FVector& Location, FRotator& Rotation) const { // We are in the SIE(Simulate In Editor) if (GEditor->bIsSimulatingInEditor // class UEditorEngine* GEditor && GCurrentLevelEditingViewportClient->IsSimulateInEditorViewport()) // class FLevelEditorViewportClient* GCurrentLevelEditingViewportClient { Rotation = GCurrentLevelEditingViewportClient->GetViewRotation(); Location = GCurrentLevelEditingViewportClient->GetViewLocation(); return true; } // We are in the editor world if (GEditor->PlayWorld == nullptr) { for (const FLevelEditorViewportClient* ViewportClient : GEditor->GetLevelViewportClients()) { if (ViewportClient && ViewportClient->IsPerspective()) { Rotation = ViewportClient->GetViewRotation(); Location = ViewportClient->GetViewLocation(); return true; } } } return false; }
编辑器中(EWorldType::PIE,Play状态)
bool GetPlayerView(FVector& Location, FRotator& Rotation) const { if (GEditor->bIsSimulatingInEditor || GEditor->PlayWorld != NULL) { UWorld* SimulationWorld = GEditor->PlayWorld; for (FConstPlayerControllerIterator Iterator = SimulationWorld->GetPlayerControllerIterator(); Iterator; ++Iterator) { if (APlayerController* PlayerActor = Iterator->Get()) { PlayerActor->GetPlayerViewPoint(Location, Rotation); return true; } } } return false; }
游戏运行时(本地有多个LocalPlayer)
bool GetPlayerViews(TArray<FVector>& Locations, TArray<FRotator>& Rotations) const { UWorld* PlayWorld = GetWorld(); int32 NumPlayers = GEngine->GetNumGamePlayers(PlayWorld); if (NumPlayers == 0) { return false; } // calculate centroid location using local players views bool bCinematic = false; FVector CentroidLocation = FVector::ZeroVector; for (int32 PlayerIndex = 0; PlayerIndex < NumPlayers; ++PlayerIndex) { ULocalPlayer* Player = GEngine->GetGamePlayer(PlayWorld, PlayerIndex); if (Player && Player->PlayerController) { FVector ViewLocation; FRotator ViewRotation; Player->PlayerController->GetPlayerViewPoint(ViewLocation, ViewRotation); Locations.Add(ViewLocation); Rotations.Add(ViewRotation); CentroidLocation+= ViewLocation; bCinematic|= Player->PlayerController->bCinematicMode; } } return true; }
游戏运行时(获取本地第一个LocalPlayer)
bool GetPlayerView(FVector& Location, FRotator& Rotation) const { UWorld* PlayWorld = GetWorld(); if (PlayWorld && PlayWorld->GetGameInstance()) { APlayerController* PC = PlayWorld->GetGameInstance()->GetFirstLocalPlayerController(nullptr); if (PC) { PC->GetPlayerViewPoint(Location, Rotation); } } return true; }
渲染线程(RenderThread)
将游戏线程(GameThread)的ULocalPlayer对象上的相机的位置和朝向传给渲染线程(RenderThread)的FSceneRender对象中,以供渲染线程(RenderThread)的逻辑使用
void UGameEngine::Tick( float DeltaSeconds, bool bIdleMode ) { UGameEngine::RedrawViewports() { void FViewport::Draw( bool bShouldPresent) { void UGameViewportClient::Draw() { // create the view family for rendering the world scene to the viewport's render target FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( InViewport, MyWorld->Scene, EngineShowFlags) .SetRealtimeUpdate(true));for (FLocalPlayerIterator Iterator(GEngine, MyWorld); Iterator; ++Iterator) { ULocalPlayer* LocalPlayer = *Iterator; if (LocalPlayer) { APlayerController* PlayerController = LocalPlayer->PlayerController; const int32 NumViews = bStereoRendering ? GEngine->StereoRenderingDevice->GetDesiredNumberOfViews(bStereoRendering) : 1; for (int32 i = 0; i < NumViews; ++i) { // Calculate the player's view information. FVector ViewLocation; FRotator ViewRotation; EStereoscopicPass PassType = bStereoRendering ? GEngine->StereoRenderingDevice->GetViewPassForIndex(bStereoRendering, i) : eSSP_FULL; // CalcSceneView函数中会把ViewLocation、ViewRotation赋值给FSceneView,然后添加到TArray<const FSceneView*> ViewFamily->Views数组中 LocalPlayer->CalcSceneView(&ViewFamily, ViewLocation, ViewRotation, InViewport, nullptr, PassType); // ... ... } // ... ... } } // 发送渲染命令 GetRendererModule().BeginRenderingViewFamily(SceneCanvas,&ViewFamily); { World->SendAllEndOfFrameUpdates(); // 创建场景渲染器 FSceneRenderer* SceneRenderer = FSceneRenderer::CreateSceneRenderer(ViewFamily, ...); // 参数ViewFamily会赋值给FSceneRenderer的FSceneViewFamily ViewFamily变量 // 向渲染线程发送绘制场景指令. ENQUEUE_RENDER_COMMAND(FDrawSceneCommand)( [SceneRenderer](FRHICommandListImmediate& RHICmdList) { RenderViewFamily_RenderThread(RHICmdList, SceneRenderer) { (......) // 调用场景渲染器的绘制接口. SceneRenderer->Render(RHICmdList); (......) } FlushPendingDeleteRHIResources_RenderThread(); }); } }}}}
渲染线程(RenderThread)从FSceneRenderer的ViewFamily.Views或Views上取FSceneView中的ViewLocation和ViewRotation,即为当前相机的位置和朝向 注:ViewFamily.Views和Views上存放的是同一个FSceneView对象
需要注意的是,一帧内可能同时存在多个FSceneRenderer实例
除了玩家视角相机的FSceneRender实例外,各个USceneCaptureComponent的相机也会有自己的FSceneRender实例
UActorComponent (184) USceneComponent (528) USceneCaptureComponent (720) USceneCaptureComponent2D (2368) UPlanarReflectionComponent (960) USceneCaptureComponentCube (768)
标签:视角,PlayWorld,return,ViewFamily,Iterator,ViewLocation,朝向,UE4,GEditor From: https://www.cnblogs.com/kekec/p/18415498