Tuesday, November 25, 2014

[UE4 Quick Tip] Increase Tessellation Limit

By default UE4 limits the tessellation factor to 8. This has been done for performance reasons since certain GPUs struggle a lot with high amounts of subdivision and owning an old AMD DX11 graphics card myself I can completely see where they are coming from.
If you want to increase the tessellation factor anyway take a look at these shader files

\Unreal Engine\4.x\Engine\Shaders\Tessellation.usf
\Unreal Engine\4.x\Engine\Shaders\PNTriangles.usf

and search for  the 'MaxTessFactor' variable.

//@todo: This should be vectorized and done in the MainHull shader.
float4 CompositeTessellationFactors = TessellationMultipliers * CalculateCompositeTessellationFactors(WorldPostion0,WorldPostion1,WorldPostion2);

// Limit the tessellation factor to <= 8. The multiplies and saturates handle any potential NANs/INFs in CompositeTessellationFactors.
float4 MaxTessFactor = 8.0f;
float4 InvMaxTessFactor = 1.0f / MaxTessFactor;
       
// clamp at 1 to prevent triangle to disappear with
CompositeTessellationFactors = max(1, MaxTessFactor * saturate(CompositeTessellationFactors * InvMaxTessFactor));

Changing this value will cause a full (material) shader recompilation so it'll take some time when you open the editor the first time.

Sunday, August 24, 2014

[Unreal Engine 4] Improving Screen Space Reflections

If you ever felt the need to adjust or improve the built-in screen space reflections of UE4 take a look at the ScreenSpaceReflections.usf shader file.
It's located in this directory: \Unreal Engine\4.x\Engine\Shaders\

In the SSR shader file search for this part of the code. The line number varies a bit with each engine version, but it should be somewhere around 340-350.
#if SSR_QUALITY == 1
const int NumSteps = 8;
const int NumRays = 1;
#elif SSR_QUALITY == 2
const int NumSteps = 16;
const int NumRays = 1;
#elif SSR_QUALITY == 3
const int NumSteps = 8;
const int NumRays = 4;
#else // SSR_QUALITY == 4
const int NumSteps = 12;
const int NumRays = 12;
#endif
There are 3 quality levels with 2 parameters which define the quality of reflections.

NumSteps - Number of steps. This defines the accuracy of reflections and causes a reasonable performance impact.
For any value above 32 you will hardly notice a difference
NumRays - Number of rays. Using more rays takes away the noise of reflections but is rather expensive.

The default settings are a bit strange since the number of steps drops from 16 back to 8 at quality level 3. My recommendation would be to set NumSteps to 16 for high quality. This comes at a little performance impact. You might also lower NumRays by 1 at the same time to gain back the lost FPS.

Here's a set of screenshots to demonstrate various value combinations as well as their impact on performance.

NumSteps=8 / NumRays=1

NumSteps=16 / NumRays=1

NumSteps=16 / NumRays=2

NumSteps=8 / NumRays=4

NumSteps=16 / NumRays=4

NumSteps=16 / NumRays=8

NumSteps=32 / NumRays=4

NumSteps=32 / NumRays=8

NumSteps=32 / NumRays=32

Saturday, August 23, 2014

[UE3/UE4] Ocean Waves Normals

Using the world position offset (aka vertex shader) is a popular way of creating large scale ocean waves in unreal engine 3/4. The drawback is that any kind of deformed geometry won't affect the shading at all. That's why you need to manually calculate the new normals inside the material.
To do so it is necessary to calculate the derivatives of the same function which is used to form the ocean waves. The derivatives with respect to x and y are equivalent to the red and green channel of a normal map. Given these 2 components it is possible to calculate the missing 3rd component to get the final per pixel normals.
I'm well aware that there are many ways of implementing ocean motion but I decided to only cover one approach with 2 sub-types, directional waves and circular waves.
In a realistic ocean material you would usually combine multiple waves of different size, speed, direction/position, which also means you would need to duplicate the material graphs shown in this tutorial. Personally I wouldn't calculate the normal for more than 3-4 waves to keep the overall material complexity at a moedrate level.

The material setups below will only work properly if  "Tangent Space Normal" is unchecked in the material properties. This is due to the fact that all calculations are done in world space which also means the generated normals are in world space. If you like to combine these normals with a normal map you would need to do transformation from world to tangent space first.


Directional Waves


Directional waves are based on the dot product between the world position of each pixel and a world space direction vector. This dot product gets added to the time and then fed into a sine node to move the vertices along the z-axis.



Generating normals for directional waves is rather easy. The sine node is being replaced by cosine and then multiplied by the direction vectors' x- and y-component.
In the example below you can also see that the normal intensity is automatically calculated by comparing the length and height of a wave.




Circular Waves


Circular waves are defined by an origin point and the distance between this origin and the world position. Similar to the directional wave setup this distance is added to time and then fed into a sine node.



The material setup for calculating the derivatives for circular waves is a bit more complex, because the distance node involves a square root.





[Unreal Engine 4] Custom Ambient Cubemap Post Process

When posting a quick tip about this topic several weeks ago, I wasn't very specific about how to setup the material at all... so here's the missing addendum.

When comparing the screenshots below you can clearly tell that my simplified version is not physically accurate, as it's missing a fesnel effect which would strengthen reflections at extreme angles. In addition it doesn't take MaterialAO and Specularity into account.
You can however add these missing features if you need them. For further reference you might want to take a look at the PostProcessAmbient.usf shader file to see how epic did it.


Material



Direct Light Only


Built-in Ambient Cubemap PP


Custom Ambient Cubemap PP