FSceneView* FJavascriptUMGViewportClient::CalcSceneView(FSceneViewFamily* ViewFamily)
{
	FSceneViewInitOptions ViewInitOptions;

	const FVector& ViewLocation = GetViewLocation();
	const FRotator& ViewRotation = GetViewRotation();

	const FIntPoint ViewportSizeXY = Viewport->GetSizeXY();

	FIntRect ViewRect = FIntRect(0, 0, ViewportSizeXY.X, ViewportSizeXY.Y);
	ViewInitOptions.SetViewRectangle(ViewRect);

	ViewInitOptions.ViewOrigin = ViewLocation;

	ViewInitOptions.ViewRotationMatrix = FInverseRotationMatrix(ViewRotation);
	ViewInitOptions.ViewRotationMatrix = ViewInitOptions.ViewRotationMatrix * FMatrix(
		FPlane(0, 0, 1, 0),
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, 0, 1));

	//@TODO: Should probably be locally configurable (or just made into a FMinimalViewInfo property)
	const EAspectRatioAxisConstraint AspectRatioAxisConstraint = GetDefault<ULocalPlayer>()->AspectRatioAxisConstraint;

	FMinimalViewInfo::CalculateProjectionMatrixGivenView(ViewInfo, AspectRatioAxisConstraint, Viewport, /*inout*/ ViewInitOptions);

	ViewInitOptions.ViewFamily = ViewFamily;
	ViewInitOptions.SceneViewStateInterface = ViewState.GetReference();
	ViewInitOptions.ViewElementDrawer = this;

	ViewInitOptions.BackgroundColor = GetBackgroundColor();

	//ViewInitOptions.EditorViewBitflag = 0, // send the bit for this view - each actor will check it's visibility bits against this

	// for ortho views to steal perspective view origin
	//ViewInitOptions.OverrideLODViewOrigin = FVector::ZeroVector;
	//ViewInitOptions.bUseFauxOrthoViewPos = true;

	//ViewInitOptions.CursorPos = CurrentMousePos;

	FSceneView* View = new FSceneView(ViewInitOptions);

	ViewFamily->Views.Add(View);

	View->StartFinalPostprocessSettings(ViewLocation);

	//OverridePostProcessSettings(*View);

	View->EndFinalPostprocessSettings(ViewInitOptions);

	return View;
}
void ULevelThumbnailRenderer::GetView(ULevel* Level, FSceneViewFamily* ViewFamily, int32 X, int32 Y, uint32 SizeX, uint32 SizeY) const 
{
	check(ViewFamily);

	FIntRect ViewRect(
		FMath::Max<int32>(X,0),
		FMath::Max<int32>(Y,0),
		FMath::Max<int32>(X+SizeX,0),
		FMath::Max<int32>(Y+SizeY,0));

	FBox LevelBox(0);

	if (Level->LevelBoundsActor.IsValid())
	{
		LevelBox = Level->LevelBoundsActor.Get()->GetComponentsBoundingBox();
	}
	else
	{
		LevelBox = ALevelBounds::CalculateLevelBounds(Level);
	}

	if (ViewRect.Width() > 0 && ViewRect.Height() > 0)
	{
		FSceneViewInitOptions ViewInitOptions;

		ViewInitOptions.SetViewRectangle(ViewRect);
		ViewInitOptions.ViewFamily = ViewFamily;

		const FVector ViewPoint = LevelBox.GetCenter();
		ViewInitOptions.ViewMatrix = FMatrix(
			FPlane(1,				0,				0,		0),
			FPlane(0,				-1,				0,		0),
			FPlane(0,				0,				-1,		0),
			FPlane(-ViewPoint.X,	ViewPoint.Y,	0,		1));

		const float ZOffset = WORLD_MAX;
		ViewInitOptions.ProjectionMatrix =  FReversedZOrthoMatrix(
			LevelBox.GetSize().X/2.f,
			LevelBox.GetSize().Y/2.f,
			0.5f / ZOffset,
			ZOffset
			);

		FSceneView* NewView = new FSceneView(ViewInitOptions);

		ViewFamily->Views.Add(NewView);
	}
}
void FRendererModule::GPUBenchmark(FSynthBenchmarkResults& InOut, float WorkScale)
{
	check(IsInGameThread());

	FSceneViewInitOptions ViewInitOptions;
	FIntRect ViewRect(0, 0, 1, 1);

	FBox LevelBox(FVector(-WORLD_MAX), FVector(+WORLD_MAX));
	ViewInitOptions.SetViewRectangle(ViewRect);

	// Initialize Projection Matrix and ViewMatrix since FSceneView initialization is doing some math on them.
	// Otherwise it trips NaN checks.
	const FVector ViewPoint = LevelBox.GetCenter();
	ViewInitOptions.ViewOrigin = FVector(ViewPoint.X, ViewPoint.Y, 0.0f);
	ViewInitOptions.ViewRotationMatrix = FMatrix(
		FPlane(1, 0, 0, 0),
		FPlane(0, -1, 0, 0),
		FPlane(0, 0, -1, 0),
		FPlane(0, 0, 0, 1));

	const float ZOffset = WORLD_MAX;
	ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix(
		LevelBox.GetSize().X / 2.f,
		LevelBox.GetSize().Y / 2.f,
		0.5f / ZOffset,
		ZOffset
		);

	FSceneView DummyView(ViewInitOptions);

	ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(
	  RendererGPUBenchmarkCommand,
	  FSceneView, DummyView, DummyView,
	  float, WorkScale, WorkScale,
	  FSynthBenchmarkResults&, InOut, InOut,
	{
		RendererGPUBenchmark(RHICmdList, InOut, DummyView, WorkScale);
	});
FSceneRenderer* FScene::CreateSceneRenderer( USceneCaptureComponent* SceneCaptureComponent, UTextureRenderTarget* TextureTarget, const FMatrix& ViewMatrix, const FVector& ViewLocation, float FOV, float MaxViewDistance, bool bCaptureSceneColour, FPostProcessSettings* PostProcessSettings, float PostProcessBlendWeight )
{
	FIntPoint CaptureSize(TextureTarget->GetSurfaceWidth(), TextureTarget->GetSurfaceHeight());

	FTextureRenderTargetResource* Resource = TextureTarget->GameThread_GetRenderTargetResource();
	FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
		Resource,
		this,
		FEngineShowFlags(ESFIM_Game))
		.SetResolveScene(!bCaptureSceneColour));

	// Disable features that are not desired when capturing the scene
	ViewFamily.EngineShowFlags.MotionBlur = 0; // motion blur doesn't work correctly with scene captures.
	ViewFamily.EngineShowFlags.SeparateTranslucency = 0;
	ViewFamily.EngineShowFlags.HMDDistortion = 0;
	FSceneViewInitOptions ViewInitOptions;
	ViewInitOptions.SetViewRectangle(FIntRect(0, 0, CaptureSize.X, CaptureSize.Y));
	ViewInitOptions.ViewFamily = &ViewFamily;
	ViewInitOptions.ViewMatrix = ViewMatrix;
	ViewInitOptions.BackgroundColor = FLinearColor::Black;
	ViewInitOptions.OverrideFarClippingPlaneDistance = MaxViewDistance;

	if (bCaptureSceneColour)
	{
		ViewFamily.EngineShowFlags.PostProcessing = 0;
		ViewInitOptions.OverlayColor = FLinearColor::Black;
	}

	// Build projection matrix
	{
		float XAxisMultiplier;
		float YAxisMultiplier;

		if (CaptureSize.X > CaptureSize.Y)
		{
			// if the viewport is wider than it is tall
			XAxisMultiplier = 1.0f;
			YAxisMultiplier = CaptureSize.X / (float)CaptureSize.Y;
		}
		else
		{
			// if the viewport is taller than it is wide
			XAxisMultiplier = CaptureSize.Y / (float)CaptureSize.X;
			YAxisMultiplier = 1.0f;
		}

		ViewInitOptions.ProjectionMatrix = FReversedZPerspectiveMatrix (
			FOV,
			FOV,
			XAxisMultiplier,
			YAxisMultiplier,
			GNearClippingPlane,
			GNearClippingPlane
			);
	}

	FSceneView* View = new FSceneView(ViewInitOptions);

	View->bIsSceneCapture = true;

	check(SceneCaptureComponent);
	for (auto It = SceneCaptureComponent->HiddenComponents.CreateConstIterator(); It; ++It)
	{
		// If the primitive component was destroyed, the weak pointer will return NULL.
		UPrimitiveComponent* PrimitiveComponent = It->Get();
		if (PrimitiveComponent)
		{
			View->HiddenPrimitives.Add(PrimitiveComponent->ComponentId);
		}
	}

	ViewFamily.Views.Add(View);

	View->StartFinalPostprocessSettings(ViewLocation);
	if (!bCaptureSceneColour)
	{
		View->OverridePostProcessSettings(*PostProcessSettings, PostProcessBlendWeight);
	}
	View->EndFinalPostprocessSettings();

	return FSceneRenderer::CreateSceneRenderer(&ViewFamily, NULL);
}
void UWorldThumbnailRenderer::GetView(UWorld* World, FSceneViewFamily* ViewFamily, int32 X, int32 Y, uint32 SizeX, uint32 SizeY) const 
{
	check(ViewFamily);
	check(World);
	check(World->PersistentLevel);

	FIntRect ViewRect(
		FMath::Max<int32>(X, 0),
		FMath::Max<int32>(Y, 0),
		FMath::Max<int32>(X + SizeX, 0),
		FMath::Max<int32>(Y + SizeY, 0));

	if (ViewRect.Width() > 0 && ViewRect.Height() > 0)
	{
		FBox WorldBox(0);
		TArray<ULevel*> LevelsToRender = World->GetLevels();
		for ( auto* Level : LevelsToRender )
		{
			if (Level && Level->bIsVisible)
			{
				ALevelBounds* LevelBounds = Level->LevelBoundsActor.Get();
				if (!LevelBounds)
				{
					// Ensure a Level Bounds Actor exists for future renders
					FActorSpawnParameters SpawnParameters;
					SpawnParameters.OverrideLevel = Level;
					LevelBounds = World->SpawnActor<ALevelBounds>(SpawnParameters);
					LevelBounds->UpdateLevelBoundsImmediately();
					Level->LevelBoundsActor = LevelBounds;
				}

				if (!LevelBounds->IsUsingDefaultBounds())
				{
					WorldBox += LevelBounds->GetComponentsBoundingBox();
				}
			}
		}

		UWorldThumbnailInfo* ThumbnailInfo = Cast<UWorldThumbnailInfo>(World->ThumbnailInfo);
		if (!ThumbnailInfo)
		{
			ThumbnailInfo = UWorldThumbnailInfo::StaticClass()->GetDefaultObject<UWorldThumbnailInfo>();
		}

		const FVector Origin = WorldBox.GetCenter();
		FMatrix ViewMatrix = FTranslationMatrix(-Origin);
		FMatrix ProjectionMatrix;
		float FOVScreenSize = 0; // Screen size taking FOV into account
		if (ThumbnailInfo->CameraMode == ECameraProjectionMode::Perspective)
		{
			const float FOVDegrees = 30.f;
			const float HalfFOVRadians = FMath::DegreesToRadians<float>(FOVDegrees) * 0.5f;
			const float WorldRadius = WorldBox.GetSize().Size() / 2.f;
			float TargetDistance = WorldRadius / FMath::Tan(HalfFOVRadians);

			if (ensure(ThumbnailInfo))
			{
				if (TargetDistance + ThumbnailInfo->OrbitZoom < 0)
				{
					ThumbnailInfo->OrbitZoom = -TargetDistance;
				}
			}

			float OrbitPitch = GlobalOrbitPitchOffset + ThumbnailInfo->OrbitPitch;
			float OrbitYaw = GlobalOrbitYawOffset + ThumbnailInfo->OrbitYaw;
			float OrbitZoom = TargetDistance + ThumbnailInfo->OrbitZoom;

			// Ensure a minimum camera distance to prevent problems with really small objects
			const float MinCameraDistance = 48;
			OrbitZoom = FMath::Max<float>(MinCameraDistance, OrbitZoom);

			const FRotator RotationOffsetToViewCenter(0.f, 90.f, 0.f);
			ViewMatrix = ViewMatrix *
				FRotationMatrix(FRotator(0, OrbitYaw, 0)) *
				FRotationMatrix(FRotator(0, 0, OrbitPitch)) *
				FTranslationMatrix(FVector(0, OrbitZoom, 0)) *
				FInverseRotationMatrix(RotationOffsetToViewCenter);

			ViewMatrix = ViewMatrix * FMatrix(
				FPlane(0, 0, 1, 0),
				FPlane(1, 0, 0, 0),
				FPlane(0, 1, 0, 0),
				FPlane(0, 0, 0, 1));

			const float NearPlane = 1.0f;
			ProjectionMatrix = FReversedZPerspectiveMatrix(
				HalfFOVRadians,
				1.0f,
				1.0f,
				NearPlane
				);

			FOVScreenSize = SizeX / FMath::Tan(FOVDegrees);
		}
		else if (ThumbnailInfo->CameraMode == ECameraProjectionMode::Orthographic)
		{
			FVector2D WorldSizeMin2D;
			FVector2D WorldSizeMax2D;
			switch (ThumbnailInfo->OrthoDirection)
			{
				case EOrthoThumbnailDirection::Top:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, -1, 0, 0),
						FPlane(0, 0, -1, 0),
						FPlane(0, 0, Origin.Z, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X,WorldBox.Min.Y);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X,WorldBox.Max.Y);
					break;
				case EOrthoThumbnailDirection::Bottom:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, -1, 0, 0),
						FPlane(0, 0, 1, 0),
						FPlane(0, 0, Origin.Z, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Y);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Y);
					break;
				case EOrthoThumbnailDirection::Front:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, 0, -1, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.Y, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Back:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(-1, 0, 0, 0),
						FPlane(0, 0, 1, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.Y, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Left:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(0, 0, -1, 0),
						FPlane(-1, 0, 0, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.X, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.Y, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.Y, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Right:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(0, 0, 1, 0),
						FPlane(1, 0, 0, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.X, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.Y, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.Y, WorldBox.Max.Z);
					break;
				default:
					// Unknown OrthoDirection
					ensureMsgf(false, TEXT("Unknown thumbnail OrthoDirection"));
					break;
			}

			FVector2D WorldSize2D = (WorldSizeMax2D - WorldSizeMin2D);
			WorldSize2D.X = FMath::Abs(WorldSize2D.X);
			WorldSize2D.Y = FMath::Abs(WorldSize2D.Y);
			const bool bUseXAxis = (WorldSize2D.X / WorldSize2D.Y) > 1.f;
			const float WorldAxisSize = bUseXAxis ? WorldSize2D.X : WorldSize2D.Y;
			const uint32 ViewportAxisSize = bUseXAxis ? SizeX : SizeY;
			const float OrthoZoom = WorldAxisSize / ViewportAxisSize / 2.f;
			const float OrthoWidth = FMath::Max(1.f, SizeX * OrthoZoom);
			const float OrthoHeight = FMath::Max(1.f, SizeY * OrthoZoom);

			const float ZOffset = HALF_WORLD_MAX;
			ProjectionMatrix = FReversedZOrthoMatrix(
				OrthoWidth,
				OrthoHeight,
				0.5f / ZOffset,
				ZOffset
				);

			FOVScreenSize = SizeX;
		}
		else
		{
			// Unknown CameraMode
			ensureMsgf(false, TEXT("Unknown thumbnail CameraMode"));
		}

		FSceneViewInitOptions ViewInitOptions;
		ViewInitOptions.ViewFamily = ViewFamily;
		ViewInitOptions.SetViewRectangle(ViewRect);
		ViewInitOptions.BackgroundColor = FLinearColor::Black;
		ViewInitOptions.ViewMatrix = ViewMatrix;
		ViewInitOptions.ProjectionMatrix = ProjectionMatrix;

		FSceneView* NewView = new FSceneView(ViewInitOptions);

		ViewFamily->Views.Add(NewView);

		// Tell the texture streaming system about this thumbnail view, so the textures will stream in as needed
		// NOTE: Sizes may not actually be in screen space depending on how the thumbnail ends up stretched by the UI.  Not a big deal though.
		// NOTE: Textures still take a little time to stream if the view has not been re-rendered recently, so they may briefly appear blurry while mips are prepared
		// NOTE: Content Browser only renders thumbnails for loaded assets, and only when the mouse is over the panel. They'll be frozen in their last state while the mouse cursor is not over the panel.  This is for performance reasons
		IStreamingManager::Get().AddViewInformation(Origin, SizeX, FOVScreenSize);
	}
}
Ejemplo n.º 6
0
static FSceneView& CreateSceneView( FSceneViewFamilyContext& ViewFamilyContext, FSlateBackBuffer& BackBuffer, const FMatrix& ViewProjectionMatrix )
{
	FIntRect ViewRect(FIntPoint(0, 0), BackBuffer.GetSizeXY());

	// make a temporary view
	FSceneViewInitOptions ViewInitOptions;
	ViewInitOptions.ViewFamily = &ViewFamilyContext;
	ViewInitOptions.SetViewRectangle(ViewRect);
	ViewInitOptions.ViewOrigin = FVector::ZeroVector;
	ViewInitOptions.ViewRotationMatrix = FMatrix::Identity;
	ViewInitOptions.ProjectionMatrix = ViewProjectionMatrix;
	ViewInitOptions.BackgroundColor = FLinearColor::Black;
	ViewInitOptions.OverlayColor = FLinearColor::White;

	FSceneView* View = new FSceneView( ViewInitOptions );
	ViewFamilyContext.Views.Add( View );

	/** The view transform, starting from world-space points translated by -ViewOrigin. */
	FMatrix EffectiveTranslatedViewMatrix = FTranslationMatrix(-View->ViewMatrices.PreViewTranslation) * View->ViewMatrices.ViewMatrix;

	// Create the view's uniform buffer.
	FViewUniformShaderParameters ViewUniformShaderParameters;
	ViewUniformShaderParameters.TranslatedWorldToClip = View->ViewMatrices.TranslatedViewProjectionMatrix;
	ViewUniformShaderParameters.WorldToClip = ViewProjectionMatrix;
	ViewUniformShaderParameters.TranslatedWorldToView = EffectiveTranslatedViewMatrix;
	ViewUniformShaderParameters.ViewToTranslatedWorld = View->InvViewMatrix * FTranslationMatrix(View->ViewMatrices.PreViewTranslation);
	ViewUniformShaderParameters.ViewToClip = View->ViewMatrices.ProjMatrix;
	ViewUniformShaderParameters.ClipToTranslatedWorld = View->ViewMatrices.InvTranslatedViewProjectionMatrix;
	ViewUniformShaderParameters.ViewForward = EffectiveTranslatedViewMatrix.GetColumn(2);
	ViewUniformShaderParameters.ViewUp = EffectiveTranslatedViewMatrix.GetColumn(1);
	ViewUniformShaderParameters.ViewRight = EffectiveTranslatedViewMatrix.GetColumn(0);
	ViewUniformShaderParameters.InvDeviceZToWorldZTransform = View->InvDeviceZToWorldZTransform;
	ViewUniformShaderParameters.ScreenPositionScaleBias = FVector4(0,0,0,0);
	ViewUniformShaderParameters.ViewRectMin = FVector4(ViewRect.Min.X, ViewRect.Min.Y, 0.0f, 0.0f);
	ViewUniformShaderParameters.ViewSizeAndSceneTexelSize = FVector4(ViewRect.Width(), ViewRect.Height(), 1.0f/ViewRect.Width(), 1.0f/ViewRect.Height() );
	ViewUniformShaderParameters.ViewOrigin = View->ViewMatrices.ViewOrigin;
	ViewUniformShaderParameters.TranslatedViewOrigin = View->ViewMatrices.ViewOrigin + View->ViewMatrices.PreViewTranslation;
	ViewUniformShaderParameters.DiffuseOverrideParameter = View->DiffuseOverrideParameter;
	ViewUniformShaderParameters.SpecularOverrideParameter = View->SpecularOverrideParameter;
	ViewUniformShaderParameters.NormalOverrideParameter = View->NormalOverrideParameter;
	ViewUniformShaderParameters.RoughnessOverrideParameter = View->RoughnessOverrideParameter;
	ViewUniformShaderParameters.PrevFrameGameTime = View->Family->CurrentWorldTime - View->Family->DeltaWorldTime;
	ViewUniformShaderParameters.PrevFrameRealTime = View->Family->CurrentRealTime - View->Family->DeltaWorldTime;
	ViewUniformShaderParameters.PreViewTranslation = View->ViewMatrices.PreViewTranslation;
	ViewUniformShaderParameters.CullingSign = View->bReverseCulling ? -1.0f : 1.0f;
	ViewUniformShaderParameters.NearPlane = GNearClippingPlane;
	ViewUniformShaderParameters.GameTime = View->Family->CurrentWorldTime;
	ViewUniformShaderParameters.RealTime = View->Family->CurrentRealTime;
	ViewUniformShaderParameters.Random = FMath::Rand();
	ViewUniformShaderParameters.FrameNumber = View->Family->FrameNumber;

	ViewUniformShaderParameters.DirectionalLightShadowTexture = GWhiteTexture->TextureRHI;
	ViewUniformShaderParameters.DirectionalLightShadowSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

	ViewUniformShaderParameters.ScreenToWorld = FMatrix(
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, View->ProjectionMatrixUnadjustedForRHI.M[2][2], 1),
		FPlane(0, 0, View->ProjectionMatrixUnadjustedForRHI.M[3][2], 0))
		* View->InvViewProjectionMatrix;

	ViewUniformShaderParameters.ScreenToTranslatedWorld = FMatrix(
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, View->ProjectionMatrixUnadjustedForRHI.M[2][2], 1),
		FPlane(0, 0, View->ProjectionMatrixUnadjustedForRHI.M[3][2], 0))
		* View->ViewMatrices.InvTranslatedViewProjectionMatrix;

	View->UniformBuffer = TUniformBufferRef<FViewUniformShaderParameters>::CreateUniformBufferImmediate(ViewUniformShaderParameters, UniformBuffer_SingleFrame);
	return *View;
}
void FThumbnailPreviewScene::GetView(FSceneViewFamily* ViewFamily, int32 X, int32 Y, uint32 SizeX, uint32 SizeY) const
{
    check(ViewFamily);

    FIntRect ViewRect(
        FMath::Max<int32>(X,0),
        FMath::Max<int32>(Y,0),
        FMath::Max<int32>(X+SizeX,0),
        FMath::Max<int32>(Y+SizeY,0));

    if (ViewRect.Width() > 0 && ViewRect.Height() > 0)
    {
        const float FOVDegrees = 30.f;
        const float HalfFOVRadians = FMath::DegreesToRadians<float>(FOVDegrees) * 0.5f;
        static_assert((int32)ERHIZBuffer::IsInverted != 0, "Check NearPlane and Projection Matrix");
        const float NearPlane = 1.0f;
        FMatrix ProjectionMatrix = FReversedZPerspectiveMatrix(
                                       HalfFOVRadians,
                                       1.0f,
                                       1.0f,
                                       NearPlane
                                   );

        FVector Origin(0);
        float OrbitPitch = 0;
        float OrbitYaw = 0;
        float OrbitZoom = 0;
        GetViewMatrixParameters(FOVDegrees, Origin, OrbitPitch, OrbitYaw, OrbitZoom);

        // Ensure a minimum camera distance to prevent problems with really small objects
        const float MinCameraDistance = 48;
        OrbitZoom = FMath::Max<float>(MinCameraDistance, OrbitZoom);

        const FRotator RotationOffsetToViewCenter(0.f, 90.f, 0.f);
        FMatrix ViewRotationMatrix = FRotationMatrix( FRotator(0, OrbitYaw, 0) ) *
                                     FRotationMatrix( FRotator(0, 0, OrbitPitch) ) *
                                     FTranslationMatrix( FVector(0, OrbitZoom, 0) ) *
                                     FInverseRotationMatrix( RotationOffsetToViewCenter );

        ViewRotationMatrix = ViewRotationMatrix * FMatrix(
                                 FPlane(0,	0,	1,	0),
                                 FPlane(1,	0,	0,	0),
                                 FPlane(0,	1,	0,	0),
                                 FPlane(0,	0,	0,	1));

        Origin -= ViewRotationMatrix.InverseTransformPosition( FVector::ZeroVector );
        ViewRotationMatrix = ViewRotationMatrix.RemoveTranslation();

        FSceneViewInitOptions ViewInitOptions;
        ViewInitOptions.ViewFamily = ViewFamily;
        ViewInitOptions.SetViewRectangle(ViewRect);
        ViewInitOptions.ViewOrigin = -Origin;
        ViewInitOptions.ViewRotationMatrix = ViewRotationMatrix;
        ViewInitOptions.ProjectionMatrix = ProjectionMatrix;
        ViewInitOptions.BackgroundColor = FLinearColor::Black;

        FSceneView* NewView = new FSceneView(ViewInitOptions);

        ViewFamily->Views.Add(NewView);

        NewView->StartFinalPostprocessSettings( ViewInitOptions.ViewOrigin );
        NewView->EndFinalPostprocessSettings(ViewInitOptions);

        FFinalPostProcessSettings::FCubemapEntry& CubemapEntry = *new(NewView->FinalPostProcessSettings.ContributingCubemaps) FFinalPostProcessSettings::FCubemapEntry;
        CubemapEntry.AmbientCubemap = GUnrealEd->GetThumbnailManager()->AmbientCubemap;
        const float AmbientCubemapIntensity = 1.69;
        CubemapEntry.AmbientCubemapTintMulScaleValue = FLinearColor::White * AmbientCubemapIntensity;

        // Tell the texture streaming system about this thumbnail view, so the textures will stream in as needed
        // NOTE: Sizes may not actually be in screen space depending on how the thumbnail ends up stretched by the UI.  Not a big deal though.
        // NOTE: Textures still take a little time to stream if the view has not been re-rendered recently, so they may briefly appear blurry while mips are prepared
        // NOTE: Content Browser only renders thumbnails for loaded assets, and only when the mouse is over the panel. They'll be frozen in their last state while the mouse cursor is not over the panel.  This is for performance reasons
        IStreamingManager::Get().AddViewInformation( Origin, SizeX, SizeX / FMath::Tan( FOVDegrees ) );
    }
}
void RenderLandscapeMaterialForLightmass(const FLandscapeStaticLightingMesh* LandscapeMesh, FMaterialRenderProxy* MaterialProxy, const FRenderTarget* RenderTarget)
{
	const ULandscapeComponent* LandscapeComponent = CastChecked<ULandscapeComponent>(LandscapeMesh->Component);

	const int32 SubsectionSizeQuads = LandscapeComponent->SubsectionSizeQuads;
	const int32 NumSubsections = LandscapeComponent->NumSubsections;
	const int32 ComponentSizeQuads = LandscapeComponent->ComponentSizeQuads;

	int32 PatchExpandCountX = 0;
	int32 PatchExpandCountY = 0;
	int32 DesiredSize = 1;
	const float LightMapOffset = 0.0f;
	const float LightMapRes = LandscapeComponent->StaticLightingResolution > 0.f ? LandscapeComponent->StaticLightingResolution : LandscapeComponent->GetLandscapeProxy()->StaticLightingResolution;
	const int32 LightingLOD = LandscapeComponent->GetLandscapeProxy()->StaticLightingLOD;
	const float LightMapRatio = ::GetTerrainExpandPatchCount(LightMapRes, PatchExpandCountX, PatchExpandCountY, ComponentSizeQuads, (NumSubsections * (SubsectionSizeQuads + 1)), DesiredSize, LightingLOD);

	const FVector2D PatchExpandOffset = FVector2D((float)PatchExpandCountX / (ComponentSizeQuads + 2 * PatchExpandCountX), (float)PatchExpandCountY / (ComponentSizeQuads + 2 * PatchExpandCountY)) * FVector2D(RenderTarget->GetSizeXY());
	const FVector2D PatchExpandScale = FVector2D((float)ComponentSizeQuads / (ComponentSizeQuads + 2 * PatchExpandCountX), (float)ComponentSizeQuads / (ComponentSizeQuads + 2 * PatchExpandCountY));

	TArray<FLightmassLandscapeVertex> Vertices;
	TArray<uint16> Indices;
	Vertices.Reserve(FMath::Square(NumSubsections) * 4);
	Indices.Reserve(FMath::Square(NumSubsections) * 6);

	const float fraction = 1.0f / NumSubsections;
	const FVector2D PositionScale = FVector2D(RenderTarget->GetSizeXY()) * fraction * PatchExpandScale;
	const float LayerScale = SubsectionSizeQuads;
	const float WeightmapSubsection = LandscapeComponent->WeightmapSubsectionOffset;
	const FVector2D WeightmapBias = FVector2D(LandscapeComponent->WeightmapScaleBias.Z, LandscapeComponent->WeightmapScaleBias.W);
	const FVector2D WeightmapScale = FVector2D(LandscapeComponent->WeightmapScaleBias.X, LandscapeComponent->WeightmapScaleBias.Y) * SubsectionSizeQuads;

	const int32 SubsectionX_Start = PatchExpandCountX > 0 ? -1 : 0;
	const int32 SubsectionX_End = NumSubsections + (PatchExpandCountX > 0 ? 1 : 0);
	const int32 SubsectionY_Start = PatchExpandCountY > 0 ? -1 : 0;
	const int32 SubsectionY_End = NumSubsections + (PatchExpandCountY > 0 ? 1 : 0);
	for (int32 SubsectionY = SubsectionY_Start; SubsectionY < SubsectionY_End; ++SubsectionY)
	{
		for (int32 SubsectionX = SubsectionX_Start; SubsectionX < SubsectionX_End; ++SubsectionX)
		{
			const FIntPoint UVSubsection = FIntPoint((SubsectionX >= 0 ? SubsectionX : 0),
			                                         (SubsectionY >= 0 ? SubsectionY : 0));
			const FVector2D UVScale = FVector2D((SubsectionX >= 0 && SubsectionX < NumSubsections ? 1 : 0),
			                                    (SubsectionY >= 0 && SubsectionY < NumSubsections ? 1 : 0));

			const FVector2D BasePosition = PatchExpandOffset + FVector2D(SubsectionX, SubsectionY) * PositionScale;
			const FVector2D BaseLayerCoords = FVector2D(UVSubsection) * LayerScale;
			const FVector2D BaseWeightmapCoords = WeightmapBias + FVector2D(UVSubsection) * WeightmapSubsection;

			int32 Index = Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition /*FVector2D(0, 0) * PositionScale*/, 0), FVector(BaseLayerCoords /*FVector2D(0, 0) * UVScale * LayerScale*/, 0), BaseWeightmapCoords /*FVector2D(0, 0) * UVScale * WeightmapScale*/));
			verifySlow(   Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(1, 0) * PositionScale,   0), FVector(BaseLayerCoords + FVector2D(1, 0) * UVScale * LayerScale,   0), BaseWeightmapCoords + FVector2D(1, 0) * UVScale * WeightmapScale  )) == Index + 1);
			verifySlow(   Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(0, 1) * PositionScale,   0), FVector(BaseLayerCoords + FVector2D(0, 1) * UVScale * LayerScale,   0), BaseWeightmapCoords + FVector2D(0, 1) * UVScale * WeightmapScale  )) == Index + 2);
			verifySlow(   Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(1, 1) * PositionScale,   0), FVector(BaseLayerCoords + FVector2D(1, 1) * UVScale * LayerScale,   0), BaseWeightmapCoords + FVector2D(1, 1) * UVScale * WeightmapScale  )) == Index + 3);
			checkSlow(Index + 3 <= MAX_uint16);
			Indices.Add(Index);
			Indices.Add(Index + 3);
			Indices.Add(Index + 1);
			Indices.Add(Index);
			Indices.Add(Index + 2);
			Indices.Add(Index + 3);
		}
	}

	FMeshBatch MeshElement;
	MeshElement.DynamicVertexStride = sizeof(FLightmassLandscapeVertex);
	MeshElement.UseDynamicData = true;
	MeshElement.bDisableBackfaceCulling = true;
	MeshElement.CastShadow = false;
	MeshElement.bWireframe = false;
	MeshElement.Type = PT_TriangleList;
	MeshElement.DepthPriorityGroup = SDPG_Foreground;
	MeshElement.bUseAsOccluder = false;
	MeshElement.bSelectable = false;
	MeshElement.DynamicVertexData = Vertices.GetData();
	MeshElement.VertexFactory = &LightmassLandscapeVertexFactory;
	MeshElement.MaterialRenderProxy = MaterialProxy;

	FMeshBatchElement& BatchElement = MeshElement.Elements[0];
	BatchElement.PrimitiveUniformBufferResource = &LightmassLandscapeUniformBuffer;
	BatchElement.DynamicIndexData = Indices.GetData();
	BatchElement.FirstIndex = 0;
	BatchElement.NumPrimitives = Indices.Num() / 3;
	BatchElement.MinVertexIndex = 0;
	BatchElement.MaxVertexIndex = Vertices.Num() - 1;
	BatchElement.DynamicIndexStride = sizeof(uint16);

	FSceneViewFamily ViewFamily(FSceneViewFamily::ConstructionValues(
		RenderTarget,
		NULL,
		FEngineShowFlags(ESFIM_Game))
		.SetWorldTimes(0, 0, 0)
		.SetGammaCorrection(RenderTarget->GetDisplayGamma()));

	const FIntRect ViewRect(FIntPoint(0, 0), RenderTarget->GetSizeXY());

	// make a temporary view
	FSceneViewInitOptions ViewInitOptions;
	ViewInitOptions.ViewFamily = &ViewFamily;
	ViewInitOptions.SetViewRectangle(ViewRect);
	ViewInitOptions.ViewOrigin = FVector::ZeroVector;
	ViewInitOptions.ViewRotationMatrix = FMatrix::Identity;
	ViewInitOptions.ProjectionMatrix = FCanvas::CalcBaseTransform2D(RenderTarget->GetSizeXY().X, RenderTarget->GetSizeXY().Y);
	ViewInitOptions.BackgroundColor = FLinearColor::Black;
	ViewInitOptions.OverlayColor = FLinearColor::White;

	FSceneView View(ViewInitOptions);

	ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
		CanvasFlushSetupCommand,
		const FRenderTarget*, RenderTarget, RenderTarget,
		{
			//SCOPED_DRAW_EVENT(RHICmdList, CanvasFlush);

			// Set the RHI render target.
			::SetRenderTarget(RHICmdList, RenderTarget->GetRenderTargetTexture(), FTextureRHIRef());
			// disable depth test & writes
			RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());

			const FIntRect RTViewRect = FIntRect(0, 0, RenderTarget->GetRenderTargetTexture()->GetSizeX(), RenderTarget->GetRenderTargetTexture()->GetSizeY());

			// set viewport to RT size
			RHICmdList.SetViewport(RTViewRect.Min.X, RTViewRect.Min.Y, 0.0f, RTViewRect.Max.X, RTViewRect.Max.Y, 1.0f);
		});