FVector2D SGameLayerManager::GetAspectRatioInset(ULocalPlayer* LocalPlayer) const { QUICK_SCOPE_CYCLE_COUNTER(STAT_SGameLayerManager_GetAspectRatioInset); FVector2D Offset(0.f, 0.f); if (LocalPlayer) { FSceneViewInitOptions ViewInitOptions; if (LocalPlayer->CalcSceneViewInitOptions(ViewInitOptions, LocalPlayer->ViewportClient->Viewport)) { FIntRect UnscaledViewRect = ViewInitOptions.GetConstrainedViewRect(); Offset.X = -UnscaledViewRect.Min.X; Offset.Y = -UnscaledViewRect.Min.Y; } } return Offset; }
FSceneView::FSceneView(const FSceneViewInitOptions& InitOptions) : Family(InitOptions.ViewFamily) , State(InitOptions.SceneViewStateInterface) , ViewActor(InitOptions.ViewActor) , Drawer(InitOptions.ViewElementDrawer) , ViewRect(InitOptions.GetConstrainedViewRect()) , UnscaledViewRect(InitOptions.GetConstrainedViewRect()) , UnconstrainedViewRect(InitOptions.GetViewRect()) , MaxShadowCascades(10) , WorldToMetersScale(InitOptions.WorldToMetersScale) , ProjectionMatrixUnadjustedForRHI(InitOptions.ProjectionMatrix) , BackgroundColor(InitOptions.BackgroundColor) , OverlayColor(InitOptions.OverlayColor) , ColorScale(InitOptions.ColorScale) , StereoPass(InitOptions.StereoPass) , DiffuseOverrideParameter(FVector4(0,0,0,1)) , SpecularOverrideParameter(FVector4(0,0,0,1)) , NormalOverrideParameter(FVector4(0,0,0,1)) , RoughnessOverrideParameter(FVector2D(0,1)) , HiddenPrimitives(InitOptions.HiddenPrimitives) , LODDistanceFactor(InitOptions.LODDistanceFactor) , bCameraCut(InitOptions.bInCameraCut) , bOriginOffsetThisFrame(InitOptions.bOriginOffsetThisFrame) , CursorPos(InitOptions.CursorPos) , bIsGameView(false) , bForceShowMaterials(false) , bIsViewInfo(false) , bIsSceneCapture(false) , bIsReflectionCapture(false) , bIsLocked(false) , bStaticSceneOnly(false) #if WITH_EDITOR , OverrideLODViewOrigin(InitOptions.OverrideLODViewOrigin) , bAllowTranslucentPrimitivesInHitProxy( true ) , bHasSelectedComponents( false ) #endif , FeatureLevel(InitOptions.ViewFamily ? InitOptions.ViewFamily->GetFeatureLevel() : GMaxRHIFeatureLevel) { check(UnscaledViewRect.Min.X >= 0); check(UnscaledViewRect.Min.Y >= 0); check(UnscaledViewRect.Width() > 0); check(UnscaledViewRect.Height() > 0); ViewMatrices.ViewMatrix = InitOptions.ViewMatrix; // Adjust the projection matrix for the current RHI. ViewMatrices.ProjMatrix = AdjustProjectionMatrixForRHI(ProjectionMatrixUnadjustedForRHI); // Compute the view projection matrix and its inverse. ViewProjectionMatrix = ViewMatrices.GetViewProjMatrix(); // For precision reasons the view matrix inverse is calculated independently. InvViewMatrix = ViewMatrices.ViewMatrix.Inverse(); InvViewProjectionMatrix = ViewMatrices.GetInvProjMatrix() * InvViewMatrix; bool ApplyPreViewTranslation = true; // Calculate the view origin from the view/projection matrices. if(IsPerspectiveProjection()) { ViewMatrices.ViewOrigin = InvViewMatrix.GetOrigin(); } #if WITH_EDITOR else if (InitOptions.bUseFauxOrthoViewPos) { float DistanceToViewOrigin = WORLD_MAX; ViewMatrices.ViewOrigin = FVector4(InvViewMatrix.TransformVector(FVector(0,0,-1)).GetSafeNormal()*DistanceToViewOrigin,1) + InvViewMatrix.GetOrigin(); } #endif else { ViewMatrices.ViewOrigin = FVector4(InvViewMatrix.TransformVector(FVector(0,0,-1)).GetSafeNormal(),0); // to avoid issues with view dependent effect (e.g. Frensel) ApplyPreViewTranslation = false; } // Translate world-space so its origin is at ViewOrigin for improved precision. // Note that this isn't exactly right for orthogonal projections (See the above special case), but we still use ViewOrigin // in that case so the same value may be used in shaders for both the world-space translation and the camera's world position. if(ApplyPreViewTranslation) { ViewMatrices.PreViewTranslation = -FVector(ViewMatrices.ViewOrigin); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { // console variable override static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.PreViewTranslation")); int32 Value = CVar->GetValueOnGameThread(); static FVector PreViewTranslationBackup; if(Value) { PreViewTranslationBackup = ViewMatrices.PreViewTranslation; } else { ViewMatrices.PreViewTranslation = PreViewTranslationBackup; } } #endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST) } /** The view transform, starting from world-space points translated by -ViewOrigin. */ FMatrix TranslatedViewMatrix = FTranslationMatrix(-ViewMatrices.PreViewTranslation) * ViewMatrices.ViewMatrix; // Compute a transform from view origin centered world-space to clip space. ViewMatrices.TranslatedViewProjectionMatrix = TranslatedViewMatrix * ViewMatrices.ProjMatrix; ViewMatrices.InvTranslatedViewProjectionMatrix = ViewMatrices.TranslatedViewProjectionMatrix.Inverse(); // Compute screen scale factors. // Stereo renders at half horizontal resolution, but compute shadow resolution based on full resolution. const bool bStereo = StereoPass != eSSP_FULL; const float ScreenXScale = bStereo ? 2.0f : 1.0f; ViewMatrices.ProjectionScale.X = ScreenXScale * FMath::Abs(ViewMatrices.ProjMatrix.M[0][0]); ViewMatrices.ProjectionScale.Y = FMath::Abs(ViewMatrices.ProjMatrix.M[1][1]); ViewMatrices.ScreenScale = FMath::Max( ViewRect.Size().X * 0.5f * ViewMatrices.ProjectionScale.X, ViewRect.Size().Y * 0.5f * ViewMatrices.ProjectionScale.Y ); ShadowViewMatrices = ViewMatrices; #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { // console variable override int32 Value = CVarShadowFreezeCamera.GetValueOnAnyThread(); static FViewMatrices Backup = ShadowViewMatrices; if(Value) { ShadowViewMatrices = Backup; } else { Backup = ShadowViewMatrices; } } #endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (InitOptions.OverrideFarClippingPlaneDistance > 0.0f) { const FPlane FarPlane(ViewMatrices.ViewOrigin + GetViewDirection() * InitOptions.OverrideFarClippingPlaneDistance, GetViewDirection()); // Derive the view frustum from the view projection matrix, overriding the far plane GetViewFrustumBounds(ViewFrustum,ViewProjectionMatrix,FarPlane,true,false); } else { // Derive the view frustum from the view projection matrix. GetViewFrustumBounds(ViewFrustum,ViewProjectionMatrix,false); } // Derive the view's near clipping distance and plane. // The GetFrustumFarPlane() is the near plane because of reverse Z projection. bHasNearClippingPlane = ViewProjectionMatrix.GetFrustumFarPlane(NearClippingPlane); if(ViewMatrices.ProjMatrix.M[2][3] > DELTA) { // Infinite projection with reversed Z. NearClippingDistance = ViewMatrices.ProjMatrix.M[3][2]; } else { // Ortho projection with reversed Z. NearClippingDistance = (1.0f - ViewMatrices.ProjMatrix.M[3][2]) / ViewMatrices.ProjMatrix.M[2][2]; } // Determine whether the view should reverse the cull mode due to a negative determinant. Only do this for a valid scene bReverseCulling = (Family && Family->Scene) ? FMath::IsNegativeFloat(ViewMatrices.ViewMatrix.Determinant()) : false; // OpenGL Gamma space output in GLSL flips Y when rendering directly to the back buffer (so not needed on PC, as we never render directly into the back buffer) auto ShaderPlatform = GShaderPlatformForFeatureLevel[FeatureLevel]; static bool bPlatformRequiresReverseCulling = (IsOpenGLPlatform(ShaderPlatform) && !IsPCPlatform(ShaderPlatform)); static auto* MobileHDRCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileHDR")); check(MobileHDRCvar); bReverseCulling = (bPlatformRequiresReverseCulling && MobileHDRCvar->GetValueOnAnyThread() == 0) ? !bReverseCulling : bReverseCulling; // Setup transformation constants to be used by the graphics hardware to transform device normalized depth samples // into world oriented z. InvDeviceZToWorldZTransform = CreateInvDeviceZToWorldZTransform(ProjectionMatrixUnadjustedForRHI); static TConsoleVariableData<int32>* SortPolicyCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.TranslucentSortPolicy")); TranslucentSortPolicy = static_cast<ETranslucentSortPolicy::Type>(SortPolicyCvar->GetValueOnAnyThread()); TranslucentSortAxis = GetDefault<URendererSettings>()->TranslucentSortAxis; // As the world is only accessable from the game thread, bIsGameView should be explicitly // set on any other thread. if(IsInGameThread()) { bIsGameView = (Family && Family->Scene && Family->Scene->GetWorld() ) ? Family->Scene->GetWorld()->IsGameWorld() : false; } #if WITH_EDITOR EditorViewBitflag = InitOptions.EditorViewBitflag; SelectionOutlineColor = GEngine->GetSelectionOutlineColor(); #endif }
void FSceneView::EndFinalPostprocessSettings(const FSceneViewInitOptions& ViewInitOptions) { { static const auto CVarMobileMSAA = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileMSAA")); if(CVarMobileMSAA ? CVarMobileMSAA->GetValueOnGameThread() > 1 : false) { // Turn off various features which won't work with mobile MSAA. FinalPostProcessSettings.DepthOfFieldScale = 0.0f; FinalPostProcessSettings.AntiAliasingMethod = AAM_None; } } { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.BloomQuality")); int Value = CVar->GetValueOnGameThread(); if(Value <= 0) { FinalPostProcessSettings.BloomIntensity = 0.0f; } } if(!Family->EngineShowFlags.Bloom) { FinalPostProcessSettings.BloomIntensity = 0.0f; } if(!Family->EngineShowFlags.GlobalIllumination) { FinalPostProcessSettings.LPVIntensity = 0.0f; } { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DepthOfFieldQuality")); int Value = CVar->GetValueOnGameThread(); if(Value <= 0) { FinalPostProcessSettings.DepthOfFieldScale = 0.0f; } } if(!Family->EngineShowFlags.DepthOfField) { FinalPostProcessSettings.DepthOfFieldScale = 0; } if(!Family->EngineShowFlags.Vignette) { FinalPostProcessSettings.VignetteIntensity = 0; FinalPostProcessSettings.VignetteColor = FLinearColor(0.0f, 0.0f, 0.0f); } if(!Family->EngineShowFlags.Grain) { FinalPostProcessSettings.GrainIntensity = 0; FinalPostProcessSettings.GrainJitter = 0; } if(!Family->EngineShowFlags.CameraImperfections) { FinalPostProcessSettings.BloomDirtMaskIntensity = 0; } if(!Family->EngineShowFlags.AmbientCubemap) { FinalPostProcessSettings.ContributingCubemaps.Empty(); } if(!Family->EngineShowFlags.LensFlares) { FinalPostProcessSettings.LensFlareIntensity = 0; } #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { float Value = CVarExposureOffset.GetValueOnGameThread(); FinalPostProcessSettings.AutoExposureBias += Value; } #endif { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.ScreenPercentage")); float Value = CVar->GetValueOnGameThread(); if(Value >= 0.0) { FinalPostProcessSettings.ScreenPercentage = Value; } } #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { float Value = CVarSSRMaxRoughness.GetValueOnGameThread(); if(Value >= 0.0f) { FinalPostProcessSettings.ScreenSpaceReflectionMaxRoughness = Value; } } #endif { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.AmbientOcclusionStaticFraction")); float Value = CVar->GetValueOnGameThread(); if(Value >= 0.0) { FinalPostProcessSettings.AmbientOcclusionStaticFraction = Value; } } if(!Family->EngineShowFlags.ScreenPercentage || bIsSceneCapture || bIsReflectionCapture) { FinalPostProcessSettings.ScreenPercentage = 100; } if(!Family->EngineShowFlags.AmbientOcclusion) { FinalPostProcessSettings.AmbientOcclusionIntensity = 0; } { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.AmbientOcclusionRadiusScale")); float Scale = FMath::Clamp(CVar->GetValueOnGameThread(), 0.1f, 5.0f); FinalPostProcessSettings.AmbientOcclusionRadius *= Scale; } { float Scale = FMath::Clamp(CVarSSAOFadeRadiusScale.GetValueOnGameThread(), 0.01f, 50.0f); FinalPostProcessSettings.AmbientOcclusionDistance *= Scale; } { float Value = FMath::Clamp(CVarMotionBlurScale.GetValueOnGameThread(), 0.0f, 50.0f); FinalPostProcessSettings.MotionBlurAmount *= Value; } { float Value = CVarMotionBlurMax.GetValueOnGameThread(); if(Value >= 0.0f) { FinalPostProcessSettings.MotionBlurMax = FMath::Min(FinalPostProcessSettings.MotionBlurMax, Value); } } { float Value = CVarSceneColorFringeMax.GetValueOnGameThread(); if (Value >= 0.0f) { FinalPostProcessSettings.SceneFringeIntensity = FMath::Min(FinalPostProcessSettings.SceneFringeIntensity, Value); } } if (!Family->EngineShowFlags.Lighting || !Family->EngineShowFlags.GlobalIllumination) { FinalPostProcessSettings.IndirectLightingColor = FLinearColor(0,0,0,0); FinalPostProcessSettings.IndirectLightingIntensity = 0.0f; } // Anti-Aliasing { const auto FeatureLevel = GetFeatureLevel(); static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.PostProcessAAQuality")); static auto* MobileHDRCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileHDR")); static auto* MobileMSAACvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileMSAA")); static uint32 MSAAValue = GShaderPlatformForFeatureLevel[FeatureLevel] == SP_OPENGL_ES2_IOS ? 1 : MobileMSAACvar->GetValueOnGameThread(); int32 Quality = FMath::Clamp(CVar->GetValueOnGameThread(), 0, 6); if( !Family->EngineShowFlags.PostProcessing || !Family->EngineShowFlags.AntiAliasing || Quality <= 0 // Disable antialiasing in GammaLDR mode to avoid jittering. || (FeatureLevel == ERHIFeatureLevel::ES2 && MobileHDRCvar->GetValueOnGameThread() == 0) || (FeatureLevel <= ERHIFeatureLevel::ES3_1 && (MSAAValue > 1))) { FinalPostProcessSettings.AntiAliasingMethod = AAM_None; } if( FinalPostProcessSettings.AntiAliasingMethod == AAM_TemporalAA) { if( !Family->EngineShowFlags.TemporalAA || !Family->bRealtimeUpdate || Quality < 3 ) { FinalPostProcessSettings.AntiAliasingMethod = AAM_FXAA; } } } if (AllowDebugViewmodes()) { ConfigureBufferVisualizationSettings(); } #if WITH_EDITOR FHighResScreenshotConfig& Config = GetHighResScreenshotConfig(); // Pass highres screenshot materials through post process settings FinalPostProcessSettings.HighResScreenshotMaterial = Config.HighResScreenshotMaterial; FinalPostProcessSettings.HighResScreenshotMaskMaterial = Config.HighResScreenshotMaskMaterial; FinalPostProcessSettings.HighResScreenshotCaptureRegionMaterial = NULL; // If the highres screenshot UI is open and we're not taking a highres screenshot this frame if (Config.bDisplayCaptureRegion && !GIsHighResScreenshot) { // Only enable the capture region effect if the capture region is different from the view rectangle... if ((Config.UnscaledCaptureRegion != ViewRect) && (Config.UnscaledCaptureRegion.Area() > 0) && (State != NULL)) { // ...and if this is the viewport associated with the highres screenshot UI auto ConfigViewport = Config.TargetViewport.Pin(); if (ConfigViewport.IsValid() && Family && Family->RenderTarget == ConfigViewport->GetViewport()) { static const FName ParamName = "RegionRect"; FLinearColor NormalizedCaptureRegion; // Normalize capture region into view rectangle NormalizedCaptureRegion.R = (float)Config.UnscaledCaptureRegion.Min.X / (float)ViewRect.Width(); NormalizedCaptureRegion.G = (float)Config.UnscaledCaptureRegion.Min.Y / (float)ViewRect.Height(); NormalizedCaptureRegion.B = (float)Config.UnscaledCaptureRegion.Max.X / (float)ViewRect.Width(); NormalizedCaptureRegion.A = (float)Config.UnscaledCaptureRegion.Max.Y / (float)ViewRect.Height(); // Get a MID for drawing this frame and push the capture region into the shader parameter FinalPostProcessSettings.HighResScreenshotCaptureRegionMaterial = State->GetReusableMID(Config.HighResScreenshotCaptureRegionMaterial); FinalPostProcessSettings.HighResScreenshotCaptureRegionMaterial->SetVectorParameterValue(ParamName, NormalizedCaptureRegion); } } } #endif // WITH_EDITOR // Upscaling or Super sampling { float LocalScreenPercentage = FinalPostProcessSettings.ScreenPercentage; float Fraction = 1.0f; // apply ScreenPercentage if (LocalScreenPercentage != 100.f) { Fraction = FMath::Clamp(LocalScreenPercentage / 100.0f, 0.1f, 4.0f); } // Window full screen mode with upscaling bool bFullscreen = false; if (GEngine && GEngine->GameViewport && GEngine->GameViewport->GetWindow().IsValid()) { bFullscreen = GEngine->GameViewport->GetWindow()->GetWindowMode() != EWindowMode::Windowed; } check(Family->RenderTarget); if (bFullscreen) { // CVar mode 2 is fullscreen with upscale if(GSystemResolution.WindowMode == EWindowMode::WindowedFullscreen) { // FIntPoint WindowSize = Viewport->GetSizeXY(); FIntPoint WindowSize = Family->RenderTarget->GetSizeXY(); // allow only upscaling float FractionX = FMath::Clamp((float)GSystemResolution.ResX / WindowSize.X, 0.1f, 4.0f); float FractionY = FMath::Clamp((float)GSystemResolution.ResY / WindowSize.Y, 0.1f, 4.0f); // maintain a pixel aspect ratio of 1:1 for easier internal computations Fraction *= FMath::Max(FractionX, FractionY); } } #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if(CVarScreenPercentageEditor.GetValueOnAnyThread() == 0) { bool bNotInGame = GEngine && GEngine->GameViewport == 0; if(bNotInGame) { Fraction = 1.0f; } } #endif // Upscale if needed if (Fraction != 1.0f) { // compute the view rectangle with the ScreenPercentage applied const FIntRect ScreenPercentageAffectedViewRect = ViewInitOptions.GetConstrainedViewRect().Scale(Fraction); SetScaledViewRect(ScreenPercentageAffectedViewRect); } } }