rendering a 360 Panorama (Cyclorama) to 8 screens

Hi,
for testing I am using the first person shooter template.
I want to render a 360 panorama aka a cyclorama. I tried using a scene capture cube, but of course that fails because of bad performance. So, I tried positioning 8 Scene Capture 2D cameras each covering 45° FOV and that gives me quite decent performance (about 30 FPS). Just for testing I fed the output to texture targets each having a 1024x512 resolution, then created a material and rendered them to some kind of “video wall” made from 8 cubes.
Now, how do I render all of the textures into a single large image and display it on the screen inside the view port?

Is there a better or alternative way of doing it?

I have got a decent setup to work with:

Ubuntu Linux 14.04 LTS
Intel(R) Xeon(R) CPU E3-1240 v3 @ 3.40GHz
16 GB RAM
256 GB SSD
2x Radeon HD 7850 Eyefinity and 9 Displays.

Thanks in advance!

What you are trying to do? Some real life panorama on 8 monitors or in game panorama?
If that is in game it is singleplayer or multiplayer? Is view trough panorama interactive (ie. can one player influence what another can see on panorama display?).
Can this whole panorama be seen at once by one player?

Your approach while easy on game designer side is very resource wasteful.

Instead you should do trigonometry:
Flatten your problem to circle and single camera represented by triangle.
Now calculate what portion of circle that triangle camera can see. Add like 5% margins on sides.
Render only that (ie. place single 2d camera in word and render to texture.
Then pan that panorama circle to face correct direction.

Math for it is very simple for situation when player is always in center of panorama, gets a bit nasty if player can move.
But it is just elementary school trigonometry.

PS. I would start testing with making panorama camera fov 5% bigger, matching it rotation directly to player camera rotation, then rotating panorama circle to same direction.
This should work fine if player is in middle of panorama.

It’s not actually a game. It’s for walking around in a maze having a 360 view. It’s indeed for some real life panorama on 8 monitors. The 8 screens are arranged in a circle. The panorama can be seen at once all the time. Instead of using 8 cameras I could also get away with 4 cameras each covering 90° FOV. The player itself can only move in a straight line and does not rotate. The viewer of the panorama therefore can also only move in a straight line and the viewer’s rotation never cause rotations of the player.
I have made a little sketch to illustrate what I mean.


hint: a cyclorama is a moving panorama.
What I simply don’t know right no is how to render the whole panorama at once on the 8 screens. That is, if I am going with what I have described I don’t know how to render the textures side by side. I also think that using one large borderless window for presenting the whole panorama is certainly easier than 8 separate windows.

Great project.

Forget all scene capture actors, they are not meant for quality of renders you probably need. And this would eat a lot of fps.

Instead You should try multiplayer setup with each player covering 90deg (or 45).
If you can setup unreal to always target same monitor, you will be almost there.
Also with multiplayer built in from beginning you will get easy way to expand for multiple PCs.

So set up multiplayer, make player controller send exactly same input to all pawns (that control cameras).
For this create function in player controller that tells location and rotation of player, make all pawns register to it, and follow player location.
At Event BeginGame assign monitors ids and add correct local rotation to their cameras.

Then you can add some umg gui to assign each player pawn to separate (or same PC).

Thanks!
For now, I am staying with a single computer, because multiple computers will cost about 4500€ extra.
My template for playing around is the first person shooter template. There is no multiplayer template, so, I can just add more pawns to that and follow your instructions, right?
After reading your advice, I searched the forum and found Come Learn Blueprint Multiplayer with me! (aka Tom's a Glutton for Punishment) - Blueprint Visual Scripting - Unreal Engine Forums
I think I can at least learn a lot from this post.
Btw. I just started last monday installing UE4. Before that, I have never ever used a game engine. I have been programming for over 20 years, though. I was almost about to buy Leadwerks, since it’s cheap and runs on Linux. So far I can honestly say, that UE4 is an absolute joy to use and super easy to build. There is still tons of stuff to figure out.
I will post some pictures of my setup If I get something to run.

Thanks!
For now, I am staying with a single computer, because multiple computers will cost about 4500€ extra.
My template for playing around is the first person shooter template. There is no multiplayer template, so, I can just add more pawns to that and follow your instructions, right?
After reading your advice, I searched the forum and found Come Learn Blueprint Multiplayer with me! (aka Tom's a Glutton for Punishment) - Blueprint Visual Scripting - Unreal Engine Forums
I think I can at least learn a lot from this post.
Btw. I just started last monday installing UE4. Before that, I have never ever used a game engine. I have been programming for over 20 years, though. I was almost about to buy Leadwerks, since it’s cheap and runs on Linux. So far I can honestly say, that UE4 is an absolute joy to use and super easy to build. There is still tons of stuff to figure out.

With “So set up multiplayer, make player controller send exactly same input to all pawns (that control cameras).” you mean, that I’ll take the first player (pawn) and attach all the other players (pawns) to him? I just tried this and if I move the first player (master) in the editor all of it’s slaves, the attached players. move accordingly, which is what I want.
I still have to figure out how to assign the the monitor id to the camera. Ok, I added Event Begin Play within the BP editor. I don’t see how to assign a monitor ID.

You need multiplayer to have multiple pawns display their cameras.
But you can have up to 4 multiplayer instances of unreal on single pc (i think its 4). So you can develop just with one pc.
However i strongly recommend that you make sure this multiplayer idea will work in cooked/released game before you develop further.

There is probably way to make multiple camera viewports without multiplayer, but that requires C++.

Monitor ID may be problem, for monitor ID i mean viewport placement on monitor, you need read information from windows about where is which monitor.
Then move viewport there. You could always duplicate that multimonitor setup from windows and let user point which monitor output is for which view.
Then you move viewport to that desktop coordinates. However i am not sure if this is doable from blueprints.

As for pawns. You need to make pawn that is camera only, and always snaps to location that player controller has exposed as variable or dispatcher or function, interface.
Yes multiple ways to do it, but dispatchers are best for this imo.

Ps. I also need to learn multiplayer someday, its on my todolist.

I am not afraid of C++. I use it every week.
“However I strongly recommend that you make sure this multiplayer idea will work in cooked/released game before you develop further.”
Even if it only works in the editor, it would be fine.
What exactly do you mean with “dispatchers”?
Auto possess and receive input from other players only works for multiplayer, right?

Event Dispatchers - learn about them, they are great for many things. They are basically functions that you can bind to from other blueprints.
When Owner blueprint calls this function, every blueprint that registered will get event with variables passed from owner.

For your project:

  • create event dispatcher in player controller, give ti variables that pass your player location.
  • in pawn blueprints create bind (Assigned) events that point to player controller dispatcher.
  • call that dispatcher function every tick from player controller, all pawns will receive events with updated location

You kind of cannot autoposses multiple pawns by single player, s you need to make this part of communication by yourself.
And best for this are dispatchers.

Ps. Dispatchers solve most of cast to problems, you cast to once at begin play, no more Cthulhu cast to mess in every single graph.

Ok, I think I need to look at a few MP examples / projects.
If I take the first person shooter template and change the number of players to 4, I get 4 windows, each showing the view of a player. From my understanding, those players can be controlled by the server, why do I need an extra camera/pawn?

You can posses only one pawn per player. They all are also on separate pcs (or in separate engine instances).
So you should reserve pawn and player controller for actual player.

Make pawn that is only flying camera. That can update its location and rotation from real player controller over neetwork.
Use those camera pawns to display viewports on monitors.

Not sure if dispatchers work over network but if they do they are best for this task of updating locations.

I am currently watching: https://www.youtube.com/watch?v=TbaOyvWfJE0&list=PL7OpsBgBjeGLHOYHvQ7AH0YSuGqvhlSIr
and looking at code dealing with multiplayer.
One little thing. If I start the First Person Template from within the Editor, the mouse is captured all the time. I this the default behavior?

Little update: I am still learning about network and multiplayer, but I think I might get away with a super simple solution.

Just a thought:
Eventually, the player will be controlled by video tracking the viewer inside a real life cyclorama, therfore his movement will be represented by two numbers indicating a relative movement in x and y direction, which is a simple movement vector.
Using a listen-server, I am thinking about sending values coming from video tracking to the listen server using a few lines of c++, make them available to blueprint and then make them “RepNotify” to propagate them to the clients. Now, all network players are identical, except the fact that depending on the player-id, the camera is facing into a different direction and this direction has to be set once during start up. Later, all the players are moving into the same direction and the corrections of the movement vector depending on the initial rotation of the camera can be made due to RepNotify.
I am going to make a simple example, which just propagates values (read from a game pad) to other clients and displays them on the screen.

C++ seems to make everything soooo much easier! UE4 is epic! .-D

Ok, I have learned quite a lot recently about using UE4.
One way for assigning a player a specific camera is iterating over all the cameras as a server and building an index using the playerController->PlayerState->PlayerId. Using this index, you can now assign each playerController it’s camera using pc->SetViewTarget();
Another method is using Auto Player Activation to assign a camera to a specific player.

Great you sorted it all. I have no idea about specific of multiplayer in Unreal. Doing mobile game all the time.
Also sadly C++ is out of the question for me (multiplatform and we do not have apple PC for compiling C++ for ios).
Blueprints are great for small tasks, with bigger project we already suffer like 20% (or more) time wasted on blueprint quirks.

it works!
First, I started with an empty Blueprint project, created a game mode, keyboard mappings (ASDW), created a player character by adding CPP-Code and 8 cameras. I then attached all those cameras to the cpp-character. Also, each camera is assigned to a corresponding player. Player0 is auto possessed.

The movement handling is done in CPP like this:

AMyCPPCharacter::AMyCPPCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don’t need it.
PrimaryActorTick.bCanEverTick = true;
}

// Called when the game starts or when spawned
void AMyCPPCharacter::BeginPlay()
{
Super::BeginPlay();

}

// Called every frame
void AMyCPPCharacter::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );

}

// Called to bind functionality to input
void AMyCPPCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
// set up gameplay key bindings
InputComponent->BindAxis(“MoveForward”, this, &AMyCPPCharacter::MoveForward);
InputComponent->BindAxis(“MoveRight”, this, &AMyCPPCharacter::MoveRight);
Super::SetupPlayerInputComponent(InputComponent);
}

void AMyCPPCharacter::MoveForward(float Value)
{
if ( (Controller != NULL) && (Value != 0.0f) )
{
// find out which way is forward
FRotator Rotation = Controller->GetControlRotation();
// Limit pitch when walking or falling
if (GetCharacterMovement()->IsMovingOnGround() || GetCharacterMovement()->IsFalling() )
{
Rotation.Pitch = 0.0f;
}
// add movement in that direction
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
}

void AMyCPPCharacter::MoveRight(float Value)
{
if ( (Controller != NULL) && (Value != 0.0f) )
{
// find out which way is right
const FRotator Rotation = Controller->GetControlRotation();
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
// add movement in that direction
AddMovementInput(Direction, Value);
}
}

The result looks like this:

I can control the player in the top left window and the movement is shown in all the other windows. I did not even need to iterate over the actors and propagate the movement.
As always…, once you have figured it out it’s actually very easy to do!
And the performance is quite good compared to the screenshot method.

What’s left to do is creating a beautiful maze and maybe also a beautiful landscape.
In retrospect, I find this way to be quite elegant. I am very happy with this solution!
UE4 is epic!

Would you consider making this available through the marketplace?

No problem!
But, and that might be a stupid question What exactly do you want me to make available?