My name is Arthô Pacini, I am the Unreal Engine 4 main developer at Fuel 3D and in this article we will share with you the MAKING OF 'Flor de Liz', a project from Modulare, all the softwares used and the general details.
The Flor de Liz project consists of 7 apartments, of these, 3 single and 4 duplex. The model chosen for the construction of this article was the first duplex.
The company served in this project is Modulare, located in Florianópolis (SC). Its concept, as its name suggests, is to offer modular apartments. These, in turn, are modified according to the customer's needs, allowing to increase, decrease and divide spaces for rental (airbnb) or commercial area (coworking / office).
The idea of using virtual reality arose from the difficulty faced by Modulare to present this concept to its customers.
All modeling of the structure was built in 3DS Max Studio from a CAD plant. Our artists built the entire base of the design in Low-Poly, without bevels or modifiers that increase the amount of polygons - Mesh Smooth, Turbo Smooth. The reason for this is mainly performance: the amount of triangles impacts a lot, both the offline rendering (Lightmass) and the real-time execution of the program.
This base structure contains about 310 objects, totaling 114.000 thousand triangles, a relatively low number for the entire structural base.
UVW UNWRAPPING OBJECTS FOR LIGHTMASS
Each static object that will be rendered by Lightmass must necessarily have a valid UV channel. It is common for every object to have a first channel, where materials can be applied, and a secondary channel, where Lightmap will be applied.
The rules for getting a good Lightmap are:
1. Use as much space as possible in the layout, wasting as little as possible.
2. Do not have overlapping faces.
3. Have a spacing between the islands (faces with different angles) of at least 2 pixels.
Let's take a look at the walls of the first floor:
It is possible to notice that the player will never see certain parts of the wall, for example the surroundings of the same, the top of the structure and part of the interior of the barbecue.
Wall sections never visible to the player (in red) [left]
and Wall sections visible to the player (in red) [right]
Knowing this, we have to leave only visible parts inside the UV.
The faces that will never be visible to the player are to the right, outside the UV layout, and the faces that will be visible to the player are left in the layout. Whatever opportunity we take we'll remove parts that are never visible, this applies to all objects in the scene.
The more space in use, higher the pixel density at lower lightmap resolutions, thus less render time and higher quality. If there are overlapping faces or the absence of 2-pixel spacing between the islands, there will be light errors in the geometry.
The Lightmap resolution values we use are as follows:
16², 32², 64², 128², 256² and 512² for small and medium sized objects such as chairs, tables, lamps, sofas and others.
1024², 2048² and 4096² for large objects such as beds, floors and walls.
Teapot with a small Lightmap resolution:
Result [left] and Lightmap density (32²) [right]
Since there is a low lightmap density it is not possible to store much information in the texture, notice that the corners of the islands are well marked, producing that dark cross in the lower left part of the teapot, exactly on the edge of the islands.
Teapot with overlapping faces:
Result [left] and Lightmap density (128²) [right]
The same teapot with a large density of pixels in the lightmap continues with errors, since the faces (islands) are superposed one on top of the others.
Teapot without overlapping faces and with a correct lightmap density:
Result [left] and Lightmap density (128²) [right]
Because we use offline renderers, our assets are composed mostly of assets ready for use in Vray and Corona, these assets are unfortunately not suitable for Unreal Engine 4.
The first reason is optimization, most assets for offline renderers have a huge amount of triangles to provide the highest quality possible, these need to be optimized to not overload the GPU when run on Unreal (heavy geometry greatly impacts real-time performance), so we have to adjust all the assets and decrease their geometric complexity.
103.016 thousand triangles [left] 40.372 thousand triangles [right]
The second model of this chair has 60% fewer triangles compared to the first model, which allows us to use two chairs at the computational price of just one. The visual dissimilarity is almost nonexistent, but the performance gained is immense. Imagine a scene where there are hundreds of instances of the same asset, optimization is a trivial process to achieve high FPS rates and ensure an uncomplicated run-time experience. We optimize about 450 objects by hand.
The second reason are in the materials and textures that accompany these assets. The materials are incompatible with Unreal and need to be rebuilt from scratch. The textures, in turn, rarely have the right dimensions for Unreal, these being 2 n, that is, the resolutions of the textures need to be in power of two, like: 16², 32², 64², 128², 256², 512², 1024², 2048² and 4096². Unreal does not like textures in which the resolution is not in power of two. The reason for this is due to the way graphic cards deal with images in memory. Using textures with different resolutions causes undesirable visual problems with the material. We use Photoshop to match the proportions of the images.
For example, a black and white zig-zag texture applied to a Utah Teapot:
511x511 [left] and 512x512 [right]
Apparently no problem right? But it is visible when we increase UV tiling:
511x511 [left] and 512x512 [right]
Even more apparent when we take a Screenshot from the Unreal Editor:
511x511 [left] and 512x512 [right]
The texture gets grainy at the corners.
95% of all the materials in the scene are built from a Master Material, which can be instantiated and parameterized easily, in addition to being compiled much faster. Our Master Material simply parameterizes the Specular, Roughness and Metallic values, as well as parameterizing the textures for Albedo, Normal and Ambient Occlusion.
We used ShaderMap and Crazybump to create Normal Maps and Ambient Occlusion from the Albedo texture.
We do not use materials directly from Vray, Corona or 3DS Max Studio, conversions never show satisfactory results and always end up disrupting the creation process. Create your own materials within Unreal.
We will not show the Master Material here in this article because we plan to develop a tutorial focused only on it, but we will show some values for each type of material in the scene:
Roughness: 0.88 ≤ x ≤ 1.0, we used 0.9 in the material in the image.
Specular: 0.45 ≤ x ≤ 1.0, we used 0.5 in the material in the image.
1024x1024 Normal Map [left] and 1024x1024 Albedo [right]
Roughness: 0.2 ≤ x ≤ 0.7, we used 0.375 in the material in the image.
In the leather of the brown chair we use as Base Color 170700FF (value in Linear Hex) and we multiply by a dirt texture, thus we create an irregularity in the color of the material.
Normal Map 1024x1024 [left] and Dirt Texture 2048x2048 [right]
Base Color: 0.0 ≤ x ≤ 1.0, we used 0.75 in the material in the image.
Roughness: 0.15 ≤ x ≤ 0.4, we used 0.25 in the material in the image.
Metallic: 1.0, never under any circumstances use any value other than 0.0 or 1.0, the idea behind this parameter is just being a Boolean value, the material is metallic or the same is non-metallic.
Roughness: 0.375 ≤ x ≤ 0.8, we used 0.5 in the material in the image.
Albedo 4096x4096 [left] and Normal Map 4096x4096 [right]
The Specular value for all materials is 0.5.
The most important part to make a realistic scene is undoubtedly the lighting. For this we use a Skylight with an HDRI from VizPark, Skydome_14.hdr.
We increased the intensity of the skylight to 1.2 and the intensity of the indirect lighting to 2.0, so we were able to light up even the darkest parts of the scene.
All internal lights have the same settings with different intensities, usually between 4 and 18 candelas. They are all static Spotlights with IES, use temperature 3800 and the attenuation radius is between 1000 and 4096.
The post-processing volume of Unreal Engine 4 is crucial to achieving maximum visual quality and photo-realistic fidelity, it is at this stage that we set the quality of the reflections and the visual effects.
Post Processing OFF [left] and Post Processing ON [right]
In the Color Grading section we have increased the contrast and minimized White Balance to remove some of the yellowish from the scene:
In the Lens section we used Chromatic Aberration, a very common visual effect on real-world camera lenses, it is very important to use this effect in any 3D Render, even if it is almost null, since every lens has a certain degree of Chromatic Aberration, this also adds a high degree of realism to 3D:
Different values for the intensity of the Chromatic Aberration:
Chromatic Aberration 0.0 [left], Chromatic Aberration 1.0 [middle] and
Chromatic Aberration 5.0 [right]
The exposure has been modified. The minimum and maximum brightness values will depend on the scene applied, there is no recipe or magic numbers, but the transition speed is something that can be applied to most scenes, we use between 15 and 20 at the transition speed.
In Image Effects we have 3 important visual effects that are extremely necessary to achieve photorealism. The first is the Vignette effect, basically darkens the corners of the image, this is caused by less light reaching the edges of the lens or film. It is an undesired effect by photography professionals, even engineers create lenses in order to lessen it, but our eyes are already so accustomed to the presence of the effect that removing it completely can cause some strangeness. We used values between 0.2 and 0.4 in Vignette.
Different values for Vignette intensity:
0.0 > 0.2 > 0.4 > 1.0
The second effect is the Grain Jitter, there is not much documentation about the effect itself, but the result is basically an erosion in neighboring pixels. We use 0.3.
Different values for Grain Jitter:
Grain Jitter 0.0 [left] and Grain Jitter 10.0 [right]
The third effect is the Grain, the granulation, which is present in all digital cameras. Like Chromatic Aberration, this effect is undesirable by professional photographers, but its use is indispensable to achieve photorealism, a Render without granulation causes the impression of being a false image, precisely because there is granulation in all the photographs. We used values between 0.1 and 0.4 for Grain, in this scene we used 0.15.
Different values for Grain intensity:
Grain Intensity 0.0 [left], Grain Intensity 0.5 [middle] and Grain Intensity 1.0 [right]
In the Rendering Features section we change the Ambient Occlusion intensity. The result of this setting is to darken the least exposed spots. We disable this setting by applying 0.0 in intensity:
Different values for Ambient Occlusion intensity:
AO 0.0 [left], AO 0.5 [middle] and AO 1.0 [right]
In Screen Space Reflections we increase the quality of the reflections to the maximum possible.
Here's a GIF showing the differences of each effect of the post-processing volume.
Static Lighting Level Scale refers to the detailing of the light evaluation, the lower this value is the more detailed the illumination will be. For fantastic results use values equal to or less than 0.35. This setting greatly increases the render time!
Num Indirect Lighting Bounces refers to the amount of times that photons can bounce from objects to other objects, this setting does not increase the render time dramatically, but it also does not increase the quality of the illumination. Use at least one value greater than 5.
Num Sky Lighting Bounces refers to the number of times that the photons emitted from the Skylight can bounce from objects to other objects. If you are using the CPU to render, use a value between 3 and 10, if you are using the GPU to render you can use the maximum value that is 100, since by our tests the GPU is much higher for this task. This setting greatly increases render time on CPU!
Indirect Lighting Quality concerns - as the name already says – to the quality of indirect lighting in general, the higher the number the higher the quality. This setting greatly increases the render time!
There is a formula to get good results with Lightmass, being:
Indirect Lighting Quality X Static Lighting Level Scale = 1.0
@Jerome Platteaux, the art director of Epic Games, has published a Master Class on lighting in the Unreal Engine, where he tests the values of the parameters mentioned above, the impact on render time and the quality of each. @Tom Looman has created an article on Platteaux's Master Class, it's worth taking a look: click here.
Static meshes: 700 +
Textures: 170 +
Materials: 200 +
Triangles: 6.750.000 +
Lightmap memory usage: 202 MB
Handmade UVW unwrapping: 700 +