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);
}
}
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)
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.
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
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
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)
@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?