I recently had a problem using Unreal Engine 4 where I wanted to give the player a clear view of the walls and objects of an interior space. This meant I had to find a way to fade out the other objects blocking the view: terrain, trees, rocks, etc. which were outside. There are several methods of doing this, but I settled on one that uses a second renderer to render only the inside and combines that with the default view using a postprocess step. I’ll go over the process here.
As a quick motivation and explanation, imagine the player is standing at the edge of a hole.
When the player jumps into the hole, they would naturally want to get a good look at all the stuff in there. But they can’t because the landscape is in the way.
What we really want is to fade out the landscape (and everything else in the way) so that the stuff underneath is visible.
There are several ways to accomplish this. A common method is to use translucent or masked materials for occluding objects. By fiddling with a specific material parameter the material can be made opaque, transparent, or somewhere in between. Normally these objects are fully opaque, but when the object is between the character and the camera the material for that object is faded to transparent. This makes objects fade out when they might obscure your view. There are several resources in forums and on Youtube that describe this method.
I chose not to go this route because it would require me to go back and rebuild many of the materials I already have. I would have switch each material’s blend mode from opaque to either translucent or masked, and add a parameter that lets me manipulate the opacity. I also need to scan for objects that should be faded out, grab their materials, and then manipulate the parameters of those materials to fade them out. Once I am using more than a few objects and materials it’s easy to fall into a special case where I missed a certain material type or object class.
The method used here doesn’t need to modify materials or specific objects. It works by rendering a second scene that only contains the objects (Actors in UE4 parlance) you want to be visible, and showing that “focused” scene instead of the default one. The main drawback of this method is that you need to render a second scene for each frame, which eats up a lot of draw calls and fill rate. But I’ll cross that bridge when I come to it.
Rendering a Second Scene
To perform this effect, the first step is to render the scene a second time from the same position with the same camera parameters (FOV, clipping, etc.). This second rendering will only show the interior space. How is this accomplished?
To render a scene outside of the normal viewport rendering, you can use the Scene Capture Component 2D. This component has two properties we are interested in:
- It renders the scene just as if you were rendering onto the main viewport, but puts the result into a render texture 2D.
- It has a “UseShowOnly” mode that will only render the Actors you specify in a variable called ShowOnlyActors
The second point lets us render only the interior. Whenever the player enters an interior region, the variable ShowOnlyActors is populated with the Actors that make up that interior along with the player avatar and anything else we still want visible from inside. Now when the SceneCaptureComponent renders it will only draw those actors.
The first point means we have a render texture that contains the interior scene. Note that the main scene is still getting rendered in the main framebuffer.
Switching to the Second Scene
We need a way to switch between the main scene and the “interior-only” scene. This is done as a separate postprocess step, which takes the two scenes as input and crossfades between the two. Normally the postprocess just uses the main scene. Once the player enters an interior it will crossfade to the second (interior-only) scene. When the player leaves the interior it will crossfade back to the main scene.
To perform all this we need to create a Dynamic Instanced Material which lets us modify the shader parameters at runtime. This is an instance of a postprocess material which does the crossfading. We then need to insert this dynamic postprocessing material into the postprocessing chaing used by the main camera. You can’t do this in the editor; you have to create the dynamic material at runtime, get the camera for your avatar, and add in the postprocessing materials.
In this blueprint I’m actually adding TWO postprocess materials; the other postprocess material adds in some rim lighting and highlights the player when they are behind things using Color Depth Postprocessing.
That’s it, now we can fade between the exterior and interior views as the player wanders around. There has to be some blueprint code to properly manipulate the fading and detect when the player enters and leaves interiors. I use overlapping volume tests to trigger the cross fade.
There are still some issues that may or may not become a problem:
-Atomospheric fog and lights are still rendered in the interior scene. This can be a problem since you may not want that stuff showing up if you’re underground. I may have to turn these off manually somehow when the player is inside.
-This method basically has to render the scene twice. This isn’t a big problem for my case since my scenes are pretty simple and the shaders are lightweight. However, for a more complicated scene or a platform with low fill-fate (mobile?) this could cause a slowdown.