How do you make a scene capture 2d orthographic

Could someone post a SceneCapture2DComponent derived class which has orthographic feature set up? Jasoncalvert’s solution probably makes sense for programmers but many of us have no idea how to do changes in C++.

I need this feature too for a dynamic minimap.

Is it possible to code necessary changes without modifying engine code itself (just by deriving)? Because that’s something I don’t want to do…

I, too, am in need of this!

Looking for this feature as well for many of same reasons already mentioned.

This feature request is still in our system, but there is currently no timeline for when it will be implemented. Our developers are currently focusing their efforts on high-priority crash and showstopper bugs.

Have a great day

Hi , This is a very much needed feature, simply for generating top-down maps that has non-disturbed view so for example a HUD overlay can be done without having to consider camera lens warping…

// type of camera
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
TEnumAsByteECameraProjectionMode::Type ProjectionMode;
UFUNCTION(BlueprintCallable, Category=Camera)
void SetProjectionMode(ECameraProjectionMode::Type InProjectionMode) { ProjectionMode = InProjectionMode; }

    // Aspect Ratio (Width/Height)
	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings, meta=(ClampMin = "0.1", ClampMax = "100.0", EditCondition="bConstrainAspectRatio"))
	float AspectRatio;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetAspectRatio(float InAspectRatio) { AspectRatio = InAspectRatio; }

    // If bConstrainAspectRatio is true, black bars will be added if  destination view has a different aspect ratio than this camera requested.
	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	uint32 bConstrainAspectRatio:1;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetConstraintAspectRatio(bool bInConstrainAspectRatio) { bConstrainAspectRatio = bInConstrainAspectRatio; }

In SceneCaptureComponent2D.h add:

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	float OrthoWidth;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetOrthoWidth(float InOrthoWidth) { OrthoWidth = InOrthoWidth; }

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	float OrthoNearClipPlane;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetOrthoNearClipPlane(float InOrthoNearClipPlane) { OrthoNearClipPlane = InOrthoNearClipPlane; }

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	float OrthoFarClipPlane;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetOrthoFarClipPlane(float InOrthoFarClipPlane) { OrthoFarClipPlane = InOrthoFarClipPlane; }

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	TEnumAsByte<ECameraProjectionMode::Type> ProjectionMode;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetProjectionMode(ECameraProjectionMode::Type InProjectionMode) { ProjectionMode = InProjectionMode; }

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings, meta=(ClampMin = "0.1", ClampMax = "100.0", EditCondition="bConstrainAspectRatio"))
	float AspectRatio;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetAspectRatio(float InAspectRatio) { AspectRatio = InAspectRatio; }

	UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
	uint32 bConstrainAspectRatio:1;
	UFUNCTION(BlueprintCallable, Category=Camera)
	void SetConstraintAspectRatio(bool bInConstrainAspectRatio) { bConstrainAspectRatio = bInConstrainAspectRatio; }

In SceneCaptureComponent.cpp in constructor for SceneCaptureComponent2D add:

OrthoWidth = 512.0f;
OrthoNearClipPlane = 0.0f;
OrthoFarClipPlane = WORLD_MAX;
ProjectionMode = ECameraProjectionMode::Perspective;
AspectRatio = 1.777778f;

Hi Sean, I think you don’t need to keep marking this answer as accepted, it’s not a bug report and there is no real answer for this question yet apart from “do it yourself” how thomie_guns has posted. Maybe you should convert his comment to an answer, but accepting this answer here doesn’t really make sense :slight_smile:

In SceneCaptureRendering.cpp under FSceneRenderer* FScene::CreateSceneRenderer, change code under build projection matrix to following:

// Build projection matrix
 {
	float XAxisMultiplier;
	float YAxisMultiplier;
	if (CaptureSize.X > CaptureSize.Y) {
		// if  viewport is wider than it is tall
		XAxisMultiplier = 1.0f;
		YAxisMultiplier = CaptureSize.X / (float)CaptureSize.Y;
	} else {
		// if  viewport is taller than it is wide
		XAxisMultiplier = CaptureSize.Y / (float)CaptureSize.X;
		YAxisMultiplier = 1.0f;
	}
    USceneCaptureComponent2D* SceneCapture2D = Cast<USceneCaptureComponent2D>(SceneCaptureComponent);
    if( SceneCapture2D && SceneCapture2D->ProjectionMode == ECameraProjectionMode::Orthographic ) {
        if (SceneCapture2D->bConstrainAspectRatio)
        {
            const float YScale = 1.0f / SceneCapture2D->AspectRatio;

            const float OrthoWidth = SceneCapture2D->OrthoWidth / 2.0f;
            const float OrthoHeight = SceneCapture2D->OrthoWidth / 2.0f * YScale;

            const float NearPlane = SceneCapture2D->OrthoNearClipPlane;
            const float FarPlane = SceneCapture2D->OrthoFarClipPlane;

            const float ZScale = 1.0f / (FarPlane - NearPlane);
            const float ZOffset = -NearPlane;

            ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix(
                OrthoWidth,
                OrthoHeight,
                ZScale,
                ZOffset
                );
        }

continued from above…

} else { 
                const float YScale = 1.0f / SceneCapture2D->AspectRatio;
    
                const float OrthoWidth = SceneCapture2D->OrthoWidth / 2.0f * XAxisMultiplier;
                const float OrthoHeight = (SceneCapture2D->OrthoWidth / 2.0f * YScale) / YAxisMultiplier;
    
                const float NearPlane = SceneCapture2D->OrthoNearClipPlane;
                const float FarPlane = SceneCapture2D->OrthoFarClipPlane;
    
                const float ZScale = 1.0f / (FarPlane - NearPlane);
                const float ZOffset = -NearPlane;
    
                ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix( OrthoWidth, OrthoHeight, ZScale, ZOffset );
            }
        } else {
            if ((int32)ERHIZBuffer::IsInverted != 0) {
                ViewInitOptions.ProjectionMatrix = FReversedZPerspectiveMatrix( FOV, FOV, XAxisMultiplier, YAxisMultiplier, GNearClippingPlane, GNearClippingPlane );
            } else {
                ViewInitOptions.ProjectionMatrix = FPerspectiveMatrix( FOV, FOV, XAxisMultiplier, YAxisMultiplier, GNearClippingPlane, GNearClippingPlane );
            }
        }

btw character limits and code formatting is terrible on these forums, no wonder there’s so little feedback compared to unity community

Thanks for code thomie! I agree character limit can be quite annoying for something like this.

Np. this sets it up so that you can switch properties on scenecapture camera just like you would on a regular camera. So make sure you change projection in inspector to orthographic, and you’ll probably want to also enable preserve aspect ratio

awesome, thank you for this!

however I’m avoiding using full source at all costs, and I see this makes changes within SceneCaptureRendering meaning I cannot just add these changes in a child of SceneCaptureComponent.

would it be too much to ask that you make a Git pull request so these changes make it into engine?

thanks again :slight_smile:

commented below that there have already been pull requests for this that have not been accepted yet.

If anyone is interested in deprojecting screen to world from capture component without rigging it up to a player controller, I made following utility function:

bool ProjectionUtils::DeprojectScreenToWorld( const FVector2D& ScreenPosition, USceneCaptureComponent2D* CaptureComponent, FVector& RayOrigin, FVector& RayDirection ) {
FTransform Transform = CaptureComponent->GetAttachmentRoot()->GetComponentTransform();


Transform.SetTranslation( FVector::ZeroVector );
FMatrix ViewRotationMatrix = ViewRotationMatrix * FMatrix (
FPlane( 0, 0, 1, 0 ),
FPlane( 1, 0, 0, 0 ),
FPlane( 0, 1, 0, 0 ),
FPlane( 0, 0, 0, 1 ) );

FIntPoint CaptureSize( CaptureComponent->TextureTarget->GetSurfaceWidth(), CaptureComponent->TextureTarget->GetSurfaceHeight() );

FSceneViewInitOptions ViewInitOptions;
ViewInitOptions.ViewOrigin = Transform.GetTranslation();
ViewInitOptions.ViewRotationMatrix = ViewRotationMatrix;
ViewInitOptions.SetViewRectangle( FIntRect( 0, 0, CaptureSize.X, CaptureSize.Y ) );

float XAxisMultiplier;
4. float YAxisMultiplier;
5. if (CaptureSize.X > CaptureSize.Y) {
6. // if viewport is wider than it is tall
7. XAxisMultiplier = 1.0f;
8. YAxisMultiplier = CaptureSize.X / (float)CaptureSize.Y;
9. } else {
10. // if viewport is taller than it is wide
11. XAxisMultiplier = CaptureSize.Y / (float)CaptureSize.X;
12. YAxisMultiplier = 1.0f;
13. }
14. USceneCaptureComponent2D* SceneCapture2D = Cast(SceneCaptureComponent);
15. if( SceneCapture2D && SceneCapture2D->ProjectionMode == ECameraProjectionMode::Orthographic ) {
16. if (SceneCapture2D->bConstrainAspectRatio)
17. {
18. const float YScale = 1.0f / SceneCapture2D->AspectRatio;
19.
20. const float OrthoWidth = SceneCapture2D->OrthoWidth / 2.0f;
21. const float OrthoHeight = SceneCapture2D->OrthoWidth / 2.0f * YScale;
22.
23. const float NearPlane = SceneCapture2D->OrthoNearClipPlane;
24. const float FarPlane = SceneCapture2D->OrthoFarClipPlane;
25.
26. const float ZScale = 1.0f / (FarPlane - NearPlane);
27. const float ZOffset = -NearPlane;
28.
29. ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix(
30. OrthoWidth,
31. OrthoHeight,
32. ZScale,
33. ZOffset
34. );
35. }

} else {
2. const float YScale = 1.0f / SceneCapture2D->AspectRatio;
3.
4. const float OrthoWidth = SceneCapture2D->OrthoWidth / 2.0f * XAxisMultiplier;
5. const float OrthoHeight = (SceneCapture2D->OrthoWidth / 2.0f * YScale) / YAxisMultiplier;
6.
7. const float NearPlane = SceneCapture2D->OrthoNearClipPlane;
8. const float FarPlane = SceneCapture2D->OrthoFarClipPlane;
9.
10. const float ZScale = 1.0f / (FarPlane - NearPlane);
11. const float ZOffset = -NearPlane;
12.
13. ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix( OrthoWidth, OrthoHeight, ZScale, ZOffset );
14. }