Recursive Rendering In UE5

I was trying to use a plugin and fix it for Unreal engine 5, this plugin was originally for ue 4.26, I managed to get it somewhat working but the recursive rendering of the render textures just dont work, what am i doing wrong? is there a specific setting that I must enable to allow for recursive rendering in unreal engine 5. Only stopped working after the upgrade. Here are also some pictures: Recursive Rendering In unreal not working - Album on Imgur

And the code for handling the recursion so as to limit to how many I want:

void APortal::UpdatePortalView()
{
	// Increase current frame count.
	currentFrameCount++;

	// Get cameras post-processing settings.
	portalCapture->PostProcessSettings = portalCharacter->Camera->PostProcessSettings;

	// Setup clip plane to cut out objects between the camera and the back of the portal.
	portalCapture->bEnableClipPlane = true;
	portalCapture->bOverride_CustomNearClippingPlane = true;
	portalCapture->ClipPlaneNormal = pTargetPortal->portalMesh->GetForwardVector();
	portalCapture->ClipPlaneBase = pTargetPortal->portalMesh->GetComponentLocation() - (portalCapture->ClipPlaneNormal * 1.0f);

	// Get the Projection Matrix from the players camera view settings.
	UEPPlayer* portalPlayer = Cast<UEPPlayer>(portalController->GetLocalPlayer());
	CHECK_DESTROY(LogPortal, !portalPlayer, "UpdatePortalView: Portal player class couldn't be found in the portal %s.", *GetName());
	portalCapture->bUseCustomProjectionMatrix = true;
	portalCapture->CustomProjectionMatrix = portalPlayer->GetCameraProjectionMatrix();

	// Get reference to player camera.
	UCameraComponent* playerCamera = portalCharacter->Camera;

	// Get the position of the main camera transform to the target portal.
	FVector newCameraLocation = ConvertLocationToPortal(playerCamera->GetComponentLocation(), this, pTargetPortal);
	FRotator newCameraRotation = ConvertRotationToPortal(playerCamera->GetComponentRotation(), this, pTargetPortal);

	// Recurse backwards for the max number of recursions and render to the texture each time overlaying each portal view.
	for (int i = recursionAmount; i >= 0; i--)
	{
		// Update location of the scene capture.
		FVector recursiveCamLoc = newCameraLocation;
		FRotator recursiveCamRot = newCameraRotation;
		for (int p = 0; p < i; p++)
		{
			recursiveCamLoc = ConvertLocationToPortal(recursiveCamLoc, this, pTargetPortal);
			recursiveCamRot = ConvertRotationToPortal(recursiveCamRot, this, pTargetPortal);
		}
		portalCapture->SetWorldLocationAndRotation(recursiveCamLoc, recursiveCamRot);

		// Use-full for debugging convert transform to target function on the camera.
		if (debugCameraTransform) DrawDebugBox(GetWorld(), recursiveCamLoc, FVector(10.0f), recursiveCamRot.Quaternion(), FColor::Red, false, 0.05f, 0.0f, 2.0f);

		UE_LOG(LogPortal, Warning, TEXT("Portals recursion amount %d"), i);

		// Set portal to not be rendered if its the first recursion event.
		// NOTE: Caps off the end so theres no visual glitches.
		if (i == recursionAmount) portalMesh->SetVisibility(false);

		// Update the portal scene capture to render it to the RT.
		portalCapture->CaptureScene();

		// Set portal to be rendered for next recursion.
		if (i == recursionAmount) portalMesh->SetVisibility(true);
	}
}

What must i change to get the Recursion to work?

BetterPortals-master.zip (19.1 MB)
You have to turn on forward shading in the project properties. I also slightly changed the capture2d component parameters (I switched to composite mode) but I’m not a 100% sure it’s needed.(did it before the forward shading change)

THANKS SO MUCH, and do you know of anyway yo make the portals more performant?

Edit:
Revised version of the update. Works with deferred rendering!


void APortal::UpdatePortalView()
{
	// Increase current frame count.
	currentFrameCount++;

	// Get cameras post-processing settings.
	portalCapture->PostProcessSettings = portalPawn->camera->PostProcessSettings;

	if (isInited == false) {
		// Setup clip plane to cut out objects between the camera and the back of the portal.
	portalCapture->bEnableClipPlane = true;
	portalCapture->bOverride_CustomNearClippingPlane = true;
	portalCapture->ClipPlaneNormal = pTargetPortal->portalMesh->GetForwardVector();
	portalCapture->ClipPlaneBase = pTargetPortal->portalMesh->GetComponentLocation() - (portalCapture->ClipPlaneNormal * 1.0f);

	// Get the Projection Matrix from the players camera view settings.
	UPortalPlayer* portalPlayer = Cast<UPortalPlayer>(portalController->GetLocalPlayer());
	CHECK_DESTROY(LogPortal, !portalPlayer, "UpdatePortalView: Portal player class couldn't be found in the portal %s.", *GetName());
	portalCapture->bUseCustomProjectionMatrix = true;
	portalCapture->CustomProjectionMatrix = portalPlayer->GetCameraProjectionMatrix();
	portalCapture->bCaptureEveryFrame = false;
	portalCapture->bCaptureOnMovement = false;
	//portalCapture->bAlwaysPersistRenderingState = true;
	isInited = true;
	}
	// Get reference to player camera.		
	UCameraComponent* playerCamera = portalPawn->camera;
	// Get the position of the main camera transform to the target portal.
	

	if (DotProductCull == true) {
		FRotator lookRot = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), playerCamera->GetComponentLocation());
		float dp = FVector::DotProduct(UKismetMathLibrary::Conv_RotatorToVector(lookRot), playerCamera->GetForwardVector());
		if (dp > 0) {
			//GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Orange, "Skipping " + GetName());
			return;
		}
	}

	FVector newCameraLocation = ConvertLocationToPortal(playerCamera->GetComponentLocation(), this, pTargetPortal);
	FRotator newCameraRotation = ConvertRotationToPortal(playerCamera->GetComponentRotation(), this, pTargetPortal);

	FVector recursiveCamLoc;
	FRotator recursiveCamRot;

	recursiveCamLoc = newCameraLocation;
	recursiveCamRot = newCameraRotation;

	// Recurse backwards for the max number of recursions and render to the texture each time overlaying each portal view.
	for (int i = recursionAmount; i >= 0; i--)
	{
		// Update location of the scene capture.
		recursiveCamLoc = newCameraLocation;
		recursiveCamRot = newCameraRotation;

		for (int p = 0; p < i; p++)
		{
			recursiveCamLoc = ConvertLocationToPortal(recursiveCamLoc, this, pTargetPortal);
			recursiveCamRot = ConvertRotationToPortal(recursiveCamRot, this, pTargetPortal);
		}

		portalCapture->SetWorldLocationAndRotation(recursiveCamLoc, recursiveCamRot);

		// Use-full for debugging convert transform to target function on the camera.
		if (debugCameraTransform) DrawDebugBox(GetWorld(), recursiveCamLoc, FVector(10.0f), recursiveCamRot.Quaternion(), FColor::Red, false, 0.05f, 0.0f, 2.0f);

		// Set portal to not be rendered if its the first recursion event.
		// NOTE: Caps off the end so theres no visual glitches.
		if (i == recursionAmount) portalMesh->SetVisibility(false);

		// Update the portal scene capture to render it to the RT.
		//portalCapture->CaptureScene();			


		FSceneInterface* Scene = GetWorld()->Scene;
		portalCapture->UpdateDeferredCaptures(Scene);
		portalCapture->CaptureSceneDeferred();

		// Set portal to be rendered for next recursion.
		if (i == recursionAmount) {			
			GetWorld()->SendAllEndOfFrameUpdates();			
			portalMesh->SetVisibility(true);
		}
	}
}

in header added

UPROPERTY()
	bool isInited = false;

The key was sending the update on the first pass so it gets registered !. No more black mirrors in the final (well first really) pass.

So with these new changes, I tried it but the recursion stopped working, is there maybe something else im doing wrong?

BetterPortals-master-deferrerd2.zip (19.1 MB)
Edit: fixed

Your produce is also experiencing this issue

ok move the
GetWorld()->SendAllEndOfFrameUpdates();
up 1 line (above the if statement).

GetWorld()->SendAllEndOfFrameUpdates();
		// Set portal to be rendered for next recursion.
		if (i == recursionAmount) {						
			portalMesh->SetVisibility(true);
		}

I forgot to test it out with multiple recursions after refactoring. It was late :stuck_out_tongue:

Thank you so much, I have been up so long trying to fix this, would you have a way of getting it so you can hold objects through the portal, kind of line in the game portal

It’s already in the project. You can pick up the cube’s with right mouse button and carry / thrown them through the portal.

The stair demo (triggered with right mouse button) also has balls falling down the strairs and going through portals.

Okay thank you so much, you have been so much :smile:

I just had a look and noticed it drops the object when you carry it through

Yeah it probably recreates it at the other side of the portal. You would need to repeat the pickup logic upon going through the portal.

Found it:

Upon entering a portal AddTrackedActor is called making a copy of the object calling CopyActor. You would need to check if the object is picked up by the player and add the logic there.

Seems it’s driven by a line trace to get the object’s logic. Might need a little rewrite to be able to store the info if an object is already held, to omit the trace and just use characterSettings.lastInteractHit

It’s a bit of a bigger rewite and out of the scope of the thread question.

Thanks very much for your help, last thing i noticed, before travelling through the portal, the player’s view looks great, after entering the portal, his view looks like a lower quality view, do you maybe know why this happens?

It’s probably the texture scaling. Hit escape and try increasing the quality of the render texture closer to 1.

Also the point of reference after travel is from before entering so it probably shifts. (you probably need to add in a delta of the vector from before the travel to not get a texture jump after travel)

Sorry Im pretty new to this whole unreal engine programming thing, whats a delta vector :grimacing:

A delta is just what changed.

@3dRaven Hi! I’m new-ish to unreal, and I’ve been trying to research portals/mirrors for animation school. I downloaded your zip file and can’t open it, it says BetterPortals’ modules are missing, then after rebuilding, it says to try rebuilding from source manually. After copying files to a project I made myself, i found that the Portal Activator blueprint has compiler errors. Is there a way i can fix this?

Right now, I’ve been trying to get that infinite effect you get from mirrors when they face each other. The idea was to research portal making to make a “mirror” appear infinite because it is actually a portal, and was wondering if you could offer some guidance?

Thank u for reading this like a year later!!

Hi. Which version of the engine are you trying to compile it in?

Hi!! Im in 5.3.2 :slight_smile: