Hello Polycounters,
I have recently received a lot of requests for tips, tutorials and tricks here in forums and on UE4 FB group regarding the work I do, some of which belong to the game I'm creating with some of my friends
[Our Ghosts of War]. I considered creating a blog but for the sake of better exposure I decided to just create a thread here. Anytime I have something to share I'll be posting in this thread and I'll be honored to answer your questions (if any).
I'm currently putting together a post about my lighting approach. If you have any requests please let me know.
Thank you.
Replies
PBR material systems introduce the need for physical lights. By that I mean we should have an idea of how much light we are casting on our materials otherwise we’re breaking the point of PBR which is achieving a more realistic look.
Unfortunately the Sun in UE4 doesn’t have any physical units such as Lux so you wouldn’t really know how much light you’re casting on your world. There are some ways to calculate this but in the end you’re not gonna have a result as pleasant as you’d have with a physical light. Now I’m gonna give you some values that I’ve found most helpful in my cases. For overcast lighting all that’s needed is a good cloudy Skydome and a Skylight intensity of 1. For a Sunny/Cloudy day a value of 3.14 as Sun intensity works well and the Skylight intensity should be reduced a little in order to maintain a good contrast between light and shadow. If we have a little less clouds and more Sun a value of 4-5 for Sun would be ideal. For those burning deserts with a violent Sun a value of 7 does wonders.
But I strongly advice everyone not to go beyond 7 as it’s going to start making your materials look worse. It kills the all the surface detail specially details in roughness are already mostly lost at this light intensity. People often go over an intensity of 10-12 to get the look they want but that’s a mistake. Either texture’s don’t have the correct luminance (they were darker than they should’ve been) or you’re a victim of UE4’s Tonemapper. UE4’s Tonemapper clamps the whites so much that initially you’re having a washed out image. To prevent that you have to have a great knowledge about tonemapper to tweak the settings very carefully while maintaining both neat white and black levels, unfortunately I'm not much of a good lighter nor I have a great knowledge about Tonemapper settings. (It's easy to tweak them and get the desired look, but it won't be correct for all scenes if it's not done properly) - (praising the lighters at DICE for their work), I choose a simpler solution here.
1. Create an empty level.
2. Remove pre-baked lighting.
3. Add two cubes, one pure black and one pure white: BaseColor 0, Specular 0, Roughness 1 and BaseColor 1, Specular 0, Roughness 1.
4. Add a directional light, set intensity value to 3.1415 (This value let's you see the true surface color) more information here.
5. Add a Post Processing Volume, set Min and Max Exposure to 1.
6. PrintScreen, paste into Photoshop.
When I color pick the left cube the value is almost 0,0,0 but when I color pick the right cube the value is 209,209,209. I want my right cube to be somewhere between 245,245,245 to 255,255,255 while my left cube stays at 0,0,0 without having to touch the Tonemapper. What I do is to simply add a Brightness/Contrast adjustment layer and increase the brightness until the right cube reads the value I want when I color pick it. The left cube would be left at 0,0,0 just like I wanted. Now I can apply this brightness adjustment to the Color Lookup Table and save it out, load it in my Post Processing Volume and voila! My whites are back.
Now I'm using this Color Lookup Table for all my works. It's not perfect, nor correct, but I'll be keep doing this until I master my Tonemapping knowledge.
Example of this Color Lookup Table with Directional Light intensity of 3.14.
Thanks for reading!
Edit:
Added missed line before taking PrintScreen: 5. Add a Post Processing Volume, set Min and Max Exposure to 1.
It doesn’t matter if it’s Megascans or what, once imported in game engine you get average looking materials.
In Megascans library you’re looking at renders on surfaces with tons of triangles. Every tiny detail is in 3D and it receives shadows plus it casts shadow as well as generating AO. But once you import materials in a game engine it’s a different story. Your surfaces in game engines are low poly, your landscape surface consists of 2 triangles per 1 square meter. There are ways to overcome this. There is a false belief among some artists which is that in a PBR engine a none metal material doesn’t need a Specular map. Another false belief is that Albedo should be free of any shadows.
Your Albedo should be free of shadows, but not any shadows. Very small scale shadows or micro shadows are something that game engines can’t take care of and these shadows need to be present on the Albedo map. To get a better knowledge of what I mean by micro shadows take a look at the image below.
Such shadows if removed from the Albedo, would not be reconstructed by the render engine no matter if you use a separate AO map or not. AO maps have no effect when the surface is lit and they only work if thesurface is covered in shadows so you really gotta keep those micro shadows in your albedo maps. Some people tend to remove those shadows then use a separate Cavity map and multiply that by Albedo in the material editor, I don’t get the point of removing them and then adding them back with the additional cost of an extra Cavity map.
Now those micro shadows represent cracks or holes on the surface and basically those cracks or holes look dark because there’s not much light being reflected from there to your eyes. But wait a second, having a constant value as specular means the entire surface is reflecting light equally which in case of the example above is incorrect behavior as there’s very little light coming from those cracks and holes to your eyes so the specular value for the cracks and holes should be less than the flat areas.
I don’t go for a separate Specular map though as that’s unnecessary memory cost. But I can easily drive a specular map from the Albedo itself by running it through a clamp node with a min value of 0 and a max value of 0.5. (0.5 is the specular for most non metals). To further introduce some more variation on the produced specular map and make the surface look more interesting we can run it through a Power node to make it more contrasty before running it through the clamp node. This makes the surfaces look more real and even behave more correctly as now the cracks and holes aren’t reflecting light as much as the flat surfaces.
Here are some pictures showing the difference between a vanilla rock material and the material plus the calculations I mentioned above. You see the second picture shows much better surface representation.
And here is a comparison while looking at the Specular buffer.
That's it for this post.
Edit: It's also nice to re-read the Specular section here: https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/
See the pictures in full res to see the differences better.
Let's compare the results of Opacity Mask Clip Value of default 0.3 vs. 0.5.
Here's a comparison, you clearly feel the flat cards in the first picture.
10. Profit.
There was a small discussion on UE4 FB group regarding using Albedo to create a Specular map. I think this deserves more clarification.
The intensity multiplier on my rock specular in the picture I posted earlier was actually low, my apologies for that. But increasing it can produce results pretty close to what an actual cavity multiplied by 0.5 does. For us I'm only doing this to save on an extra cavity map. To be honest the Megascan Albedos aren't completely shadow free so running the albedo through a Power and Multiply and finally a Clamp with min 0 max 0.5 and a little tweaking can let you amplify those shadows and use them for Spec. Here's the Spec Buffer view:
I have experimented with lots of grass meshes and lots of grass fields. One of the nicest ones for me (in terms of forms) is the one below. My goal was to create a low poly grass field that runs well and has some interesting height variations to it. So I made a lot of grass meshes and I'm gonna show the two winner meshes below.
Above is the medium grass. It's a single plane instanced 6 times. The texture that I'm using on the mesh is actually very straight grass blades material from Megascans and I couldn't really find my desired texture on the library so in order to make it look more like bent grass patches I've rotated the two instances on each end outwards. Doing this I realized the curve that's created on the top (as you're seeing in the front view) adds a ton to the look of the grass field when I'm looking at it in UE4. That curve makes it transit smoothly to the other small grass. The 3 other instanced planes are doing a great job making it look more 3D from perspectives other than front. Basically X grass as you see in the top view.
This is the mesh for the small grass:
I have been doing a lot of variations but in the end I went with this setup to have a more uniform distribution since this is actually small grass and is only there so when you look down you see some stuff going on around you, not dense at all. If you're wondering why the square shape, I'll cover that some time later. So the two grass meshes aside, I'm mostly relying on the grass material that's on the landscape surface. Here's me looking down:
When looking at a large grass field all grass meshes get culled at some distance. I did endure a lot of pain in order to make the transition from grass meshes to landscape grass material less apparent when the meshes are culled. I'll cover this at a later day as well.
Note: I'm in no way an expert in anything and in no position to try to lecture anyone. I'm sharing what I found to be the most helpful in my cases and if anything in this thread helps anyone, I'll be glad of it.
Thanks for reading.
I looked around A LOT. Spent a lot of time trying to figure out a solution. This is just another flaw of the PBR in my opinion. We have translated the real world surface rules into game engines without having the power to have the same real world geometries with trillions of triangles to apply these rules to. Looking around I noticed the Cryengine community had the same problem but Crytek has already dealt with it. This slide gave me some clues.
Here's a very very simple grass material:
And this is how it looks like on the landscape surface:
But as the sun starts to rotate, you start to have reflection problem. No where in the world a grassy ground looks like this:
So I reconstructed a Specular map using the Albedo, as I have explained in Tip 02 to prevent 100% of the surface from reflecting light equally. This is how it looks like in the material editor:
And this is how it looks like on the landscape, but it's still way off...
To reduce the specular gain I went ahead and used the Fresnel node to mask out the area where the specular is gaining, and reduced the specular intensity for those areas from 1 to 0.33. This is how it looks like in the material editor:
And finally, this is how it looks like on the landscape surface:
But still, it does look off somehow. You notice in the middle the reflection is stronger. If we had grass meshes here, when they are culled it'd look too obvious that they are disappearing and breaks the immersion into bits. Next time I'll cover how I went around this issue.
For demonstration I have used a grass material. But any material that's rough and has a lot of volumes to it in real life like grass does, it can greatly benefits from this method.
Thank you for reading!
With the release of 4.15 the LUT included in Tip 01 no longer gives correct results due to the tonemapper changes. I have created a new LUT that works correctly with 4.15 unclampes the whites. Left is with LUT, right is without.
I realized using the Levels modifier gives more accurate results over Brightness modifier. You can grab the LUT here.
Hi everyone,
And here is a comparison between 1 and 7.
Enjoy Megascanning and thanks for reading!
Thanks a lot for all this, it is really valuable to me.
Does the "AO multiplied on Abledo" means you multiply both into the colour input? I wonder if it could be done in Photoshop to save one operation (if that will have any effect).
To reconstruct normal map's blue channel:
But to answer your question more clearly, doing a multiply inside material editor doesn't hit your performance.
I now have a little issue with the LUT_2 file you have posted... LUT_1 works still realtively OK.
*edit: Silly me, I've just forgot to specify it is ColorLookupTable in the texture group in the texture details-
Hello good people of polycount.
I was working on a very small thing, mainly for learning purpose.
Usually when working on a landscape the one big issue is having no correct sense of scale. When you're doing level design it's sometimes very hard to know how everything feels from a player perspective, how big is this rock? how long is that path? how high is that hill? how large is that field? These are all sort of questions that I'm always dealing with.
When doing level design, what I've been always doing was to place the mannequin mesh here and there, look at it to get a sense of how big everything is. But that's actually not very helpful. The moment the mannequin isn't placed right next to what you're looking at, you lose the sense of scale. And on top of that, I got tired of placing mannequins here and there all the time.
For instance look at the scene below, the rocks look nice, but there's no way you'd know how big they are. And knowing the scales is actually more important than making it look good.
So what I came up with was to create a very small and simple grid function that tiles a grid on the landscape in world space, the easy way.
Here's the function:
And here's how it's setup in the landscape material. It get's all the inputs, with a BreakMaterialAttributes all outputs are broken and fed into the final input pins. Nothing complex.
A few parameters are exposed to material instance.
Opacity: Controls the grid opacity.
Specular: Preferably set to 0.
Roughness: Preferably set to 1.
Size: How much the grid is tiled.
I'm using a size of 1200 as you see. I know that makes the red squares as big to fit three sleeping dudes. (Outlined by blue).
And just knowing each red square can fit 3 sleeping dudes, I'm now instantly able to have a correct sense of scale everywhere without needing to place a mannequin or anything else, simply by changing the Grid - Opacity from 0 to 1.
Check out the squares I've outlined with green, now you know precisely how big the rocks are.
If you find this useful, you can download the function from here and put it in your content folder.
Ootrick, Thanks. For lighting after 4.15 I'm using Movable directional and Skylight + Cubemap loaded in PPV. LPVs enabled too. I have the same setup here and there, only values and cubemaps differ from project to project. My other microphone was busted, got a new one today and planning to do lots of tutorials from now. =D
Small article published here thought you might find it useful.
https://80.lv/articles/rendering-scanned-vegetation-in-real-time/
The big redwood forest breakdown is being worked on.
Good wishes, in particular.
~Ali
From large surfaces such as landscapes to smaller objects like rock formations. World space color variation is always the key to make things look more natural and interesting. This function gets your Albedo and outputs parameters to the material instance for you to introduce any sort of color variation to the surface at any scale, using a single RGB Texture Map.
You can download the function from here.
So it's quite cheap.
Glad you find it useful
Source
Again this is about large surfaces such as landscape. Variation in color makes the surfaces look nice up to a certain distance. But looking at a large surface from far away, that color variation alone isn't enough and needs to be coupled with macro normal variation to break up the lighting on the surface. Now this isn't anything complex or fancy, just a very simple function that can be helpful at times when working with landscapes or other type of vast surfaces.
You can download the function from here.
It's been a while I've been building a whole library of modular functions that I can plug and play in every material. My initial goal was to save a bunch of time every time I move to work on a new project and I feel like I've achieved it. Once starting a new project, all I'd need to do is to copy my functions library over and start placing them in my materials where needed, cutting out the need to re-do the same setups over and over again in different projects/materials. I hope these will help you save some time too.
You can of course add any other type of control inside the function.
Download the function from here.
Also do you know that you can change the inputs sort priority and thus make their order more familiar, like: red, green, blue instead of green, blue, red?
PixelGoat, Thanks man, I'm glad to hear that from you.
Another tip: use Saturate over Clamp nodes if you are after 0-1. It's cheaper, if not practically free (and the node is smaller, if you are OCD on organization).
Hi everyone!
Some might not be aware, for enabling specular occlusion from Skylight you have to put a zero in front of "r.AOSpecularOcclusionMode" cvar.
I have a extreme case showing that. Below is the comparison slide.
https://imgsli.com/MTY0NQ
Left is "r.AOSpecularOcclusionMode 1" (Specular Occlusion off).
Right is r.AOSpecularOcclusionMode 0" (Specular Occlusion on).