UE4 – Material Functions explanation and Example

Software:
Unreal Engine 4.24

Material Functions encapsulate shading flow graphs (material blueprints) into reusable shading nodes that have their own inputs and outputs.
This allows development of custom shading nodes, and saving the time it takes to recreate the same flow graphs multiple times or even copy and paste material flow graphs.
Common shading processes and operations that have to be performed in many different materials, and even multiple times in a single material can be defined as a Material Function for quick and easy re-usability.
Material functions can also be used to encapsulate a full material blueprint with a Material Attributes output. this provides a convenient workflow for blending different materials together.

In this post I’ll detail the steps needed to create and use a Material Function.
The Material Function example we’ll create, called “ColorAngleBlend” performs a commonly needed shading operation of blending 2 colors or textures according to the surface viewing angle (facing ratio).

The ColorAngleBlend Material Function will have the following inputs:

  1. color a:
    The color or texture appearing when viewing the surface at perpendicular angle.
  2. color b:
    The color or texture appearing when viewing the surface at grazing view angle.
  3. curve exponent:
    The steepness of the blend curve between the colors, 1 being a linear blend and higher values displaying color a at more angles “pushing” color b to be seen only at grazing angle.
  4. base color blend:
    The percent of color b seen at perpendicular view angle.
  5. normal:
    bump normals input.

The final “ColorAngleBlend” Material Function Blueprint:
* The internals of the “ColorAngleBlend” Material Function
Annotation 2019-12-24 151655.jpg

An example of the “ColorAngleBlend” Material Function node used to create a reach view-angle dependent color blend for a steampunk metal material:
Annotation 2019-12-24 152625

An example of the “ColorAngleBlend” Material Function node used to create a reach color for a car-paint material:
Annotation 2019-12-24 152036

An example of the “ColorAngleBlend” Material Function node used to create a washed-out effect for a cloth material:Annotation 2019-12-24 151927
Steps for creating the “ColorAngleBlend” Material Function:

  1. In the content browser, create a Material Function Object and name it “ColorAngleBlend”:
    Annotation 2019-12-24 161420
    Annotation 2019-12-24 162132
  2. Double click the ColorAngleBlend Material Function to open it for editing:
    Annotation 2019-12-24 162209
  3. Click the background of the work space to deselect the Output Result Node,
    So that the Details panel on the left will display the Material Functions‘s properties.
    Type a description into the Description field, check the Expose to Library option so that the new Material Function will be available to all materials in the Palate and node search, and define in which node categories it should appear:
    Annotation 2019-12-24 162805
  4. Select the Output Result node and in the Details panel on the left set its output name to “color”:
    Annotation 2019-12-24 163948
  5. Add a Linear Interpolate (Lerp) node, a Fresnel node and a Transform Vector (Tangent space to World space) node to the Blueprint and connect the nodes like this:
    * The Lerp node will blend the 2 color inputs with the Fresnel providing view angle data as the alpha for the Lerp.
    The Transform Vector  node is needed to convert normal (bump) input to world space for the Fresnel node.
    Annotation 2019-12-24 164646.jpg
  6. Adding function inputs:
    Create 2 Function Input nodes, in their Details panel, name them “color a” and “color b”, leave their Input Type as default Vector3D, check the option Use Preview Value as Default, number their Sort Priority parameters 0 and 1 to make them appear as the first inputs of the ColorAngleBlend node as it will appear when used in a material, and connect them to the Lerp node’s A and B inputs:
    Annotation 2019-12-24 165934
  7. Adding function inputs:
    Create 2 new Function Input nodes, name them “curve exponent” and “base color blend”, this time set their Input Type to Scalar, check the option Use Preview Value as Default, set their Sort Priority parameters to 2 and 3 and connect their outputs to the Fresnel node’s ExpoentIn and BaseReflectFractionIn inputs:
    Annotation 2019-12-24 171212.jpg
  8. Adding function inputs:
    Create the final Function Input node, name it “normal“, set its Input Type to Vector3D, check its Preview Value as Default option, set its Sort Priority to 4, and connect its output to the Fresnel node’s Normal input:
    Annotation 2019-12-24 171640
  9. Adding default inputs:
    Finally, add constant nodes to serve as default input values for the Material Function.
    A pure white Constant3Vector (color) constant as the default value for “color a” input,
    A pure black Constant3Vector (color) constant as the default value for “color a” input,
    A Constant with value 1.0 as the default value for “curve exponent” input,
    A Constant with value 0.0 as the default value for”base color blend” input,
    A pure blue Constant3Vector (color) constant as the default value for “normal” input.
    > Tip for quick creation of constant value nodes
    Annotation 2019-12-24 172438
  10. Save the new Material Function.

To use the new ColorAngleBlend Material Function create a new material, in the node search start typing color… to locate the ColorAngleBlend node and create it, and connect it to the desired material input.

Annotation 2019-12-24 173747

Annotation 2019-12-24 173809.jpg

> Material Functions can also be used by dragging them from the Content Browser into the Material Blueprint.

Related posts:
UE4 Material Instances
UE4 Fresnel node

UE4 – Create and Play a Level Sequence

Software:
Unreal Engine 4.24

To create animations and trigger them to play on game start:

First create a Level Sequence containing the animation:

  1. Create a new Level Sequence actor:
    Annotation 2019-12-23 164745
  2. Name the new Level Sequence and drag it to into the level:
    Annotation 2019-12-23 165833.jpg
  3. Select the actor you want to animate in the level and double click the Level Sequence in the Content Browser to open it in the Sequencer window:
    Annotation 2019-12-23 170453.jpg
  4. In the Sequencer window, press the +Track button to add a sequence track, choose the upper most option Actor To Sequence, the option to Add the selected actor will automatically appear first on the menu that will open on the right:
    Annotation 2019-12-23 170622
  5. Add the selected actor as a sequence track, expand the track’s Transform channels to reveal the Transform property you would like to animate, and click the + button for that channel to create the first key-frame:
    Annotation 2019-12-23 171623
  6. Activate the Create when channels/properties change option button:
    Annotation 2019-12-23 171932
  7. Move the time slider to a desired time for the motion and move/change the actors transform to create a new key-frame:
    Annotation 2019-12-23 172115.jpg

The Level Sequence now contains animation for the Actor, but when we play the game, the animation doesn’t play.
For the animation to play in game, we must trigger it fro a Blueprint, in this case the Level Blueprint:

  1. From the Editor Blueprints menu, choose Open Level Blueprint:
    Annotation 2019-12-23 173450
  2. In the Level Blueprint, drag the Event BeginPlay execution graph and create CreateLevelSequencePlayer node that will follow it:
    Annotation 2019-12-23 173759
  3. Drag the CreateLevelSequencePlayer node’s Return Value output and create a Play node that will be executed after it and receive it’s output:
    Annotation 2019-12-23 173854
  4. The Level Blueprint now has instructions to play a Level Sequence,
    but it’s not yet specified which Level Sequence to play:
    Annotation 2019-12-23 173929
  5. In the Variables list on the left, press the +Variable button to create a new variable and name it:
    Annotation 2019-12-23 174757
  6. With the new variable selected, in it’s details on the right, press the Variable Type button, and locate Level Sequence – Object Reference type:
    Annotation 2019-12-23 174932.jpg
  7. The Level Blueprint now contains a variable named seq of type: Level Sequence – Object Reference:
    Annotation 2019-12-23 175200.jpg
  8. Drag the new variable to the Blueprint and choose Get when placing it:
    Annotation 2019-12-23 175536
  9. Connect the variable’s output to the Level Sequence input of the CreateLevelSequencePlayer node:
    Annotation 2019-12-23 175609
  10. With the variable selected, in the details panel on the right, select the Level Sequence object it will be referencing:
    Annotation 2019-12-23 175627
  11. Press Compile and save the Level Blueprint:
    Annotation 2019-12-23 175646

The Level Blueprint now has instructions to play the desired Level Sequence when the level begins playing so a the animation we created plays when we hit play game in the editor:
Annotation 2019-12-23 180500

animseq.gif

 

Related:
UE4 Camera Animation

UE4 – Python – Placing level actors bottom at Z 0.0

Software:
Unreal Engine 4.22

This simple Unreal Editor Python example sets the Z axis location of all actors with names beginning with ‘Sphere_’ in a way that their bottom (minimum Z bound) is at height 0.0.

Download the script

> learn how to run Python scripts in the UE4 Editor

import unreal
from unreal import Vector

lst_actors = unreal.EditorLevelLibrary.get_all_level_actors()
print('place actors at 0 z')
for act in lst_actors:
    act_label = act.get_actor_label()
    if 'Sphere_' in act_label:
        print('placing: {}'.format(act_label))
        act_location = act.get_actor_location()
        act_bounds = act.get_actor_bounds(False)
        act_min_z = act_bounds[0].z - act_bounds[1].z
        location_offset = Vector(act_location.x, act_location.y, act_location.z - act_min_z)
        act.set_actor_location(location_offset, False, False)

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

Note:
The get_actor_bounds unreal.Actor class method returns a tuple object containing 2 unreal.Vector objects, the first being world space location of the actor geometric center, and the second is the corner of the bounding box relative to the center.

‘Sphere_*’ actors before running the script:

Annotation 2019-12-08 225356.jpg

‘Sphere_*’ actors after running the script:

Annotation 2019-12-08 225503.jpg

 

Related:
Get started with Python for Unreal Editor
UE4 – Python – Importing assets

UE4 – Package a Project for Windows

Software:
Unreal Engine 4.21

Basic steps for packaging a simple UE4 project for Windows:

Package settings:
Open the Project Settings window:
Untitled-1.jpg

  1. In: Project > Description
    Set the project’s details and thumbnail:
    > The Project thumbnail will apear in the UE4 Editor browser.
    > Thumbnail image must be a 192 x 192 resolution PNG
    Untitled-4
  2. In: Project > Maps & Modes
    Set default level (Map) for the project:
    Untitled-5
  3. In: Project > Packaging
    Choose build configuration
    > For final distribution choose ‘Shipping‘:
    Untitled-6
  4. In: Project > Supported Platforms:
    Make sure Windows is selected:
    Untitled-7.jpg

Note:
If the project folder is located within a deep folder structure, there might be packaging errors because of long file paths.
Adding a Quit command:
Select the FirstPersonCharacter Actor and enter editing mode.
In the Event Graph blueprint, add an Escape key press event node,
And connect it to a Quit command node.

Untitled-9.jpg

 

Creating the game package:
Choose:
File > Package Project > Windows > Windows (64-bit)
And select an output folder.

Untitled-8.jpg

A folder named “WindowsNoEditor” will be created,
And inside it will be the game executable along with code and assets folders.
This package can be renamed and copied to other locations.

 

UE4 – Connect a Directional Light to an Atmospheric Fog effect

Software:
Unreal Engine 4.21

UE4‘s Directional Light mimics sun lighting and shadow fairly realistically,
And the Atmospheric Fog visual effect produces a realistic clear sky background that includes the sun’s disk image in the sky.
> The Atmospheric Fog produces a result similar to an implementation of a Preetham physical sky model in common rendering software.

Combined together, these two elements can produce an effective day-light system,
But inorder for this to work the sun’s direction should be controlling the time of day simulated by the Atmospheric Fog.

For the Directional light to control the Atmospheric fog:
In the Directional Light’s details, under light, expend the settings and enable:
Atmosphere / Fog Sun Light

Note:
There is a limitation to this setup’s realism because the sunlight’s color shouldn’t be pure white, but rather yellowish, to orange, depending on the time of day (you can find tables of the sunlight’s color temperature for various time of day on the web)
There is no problem setting the sun’s color, but the problem is that it causes additional coloring of the Atmospheric Fog which isn’t needed since it already is simulating the sky’s color correctly.
The result of this limitation is that we can see a sunset sky with a white sunlight which is wrong.
I didn’t find a workaround for this yet, can’t find a way to set the Atmospheric Fog‘s sun vector without connecting it to a Directional light and can’t find a way to make the Directional Light‘s color not affect the Atmospheric Fog‘s color.

Update:
It seems this limitation can be overcome by disconnecting the Atmospheric Fog from the Directional Light and using the Atmospheric Fog Object’s rotation to control it.

Directional_light_Affect_Atmo_Fog
atmo_fog.gif

UE4 – Enable complex collision for models

Software:
Unreal Engine 4.21

By default UE4 uses fast simplified convex collision shapes to calculate collision for static mesh actors.
This means that the player or projectiles wont be able to path through holes, openings or doors in the model.

To set complex (concave) collision for a static mesh model:

In Static Mesh editing window, in the details pane, under Collision:
Set Collision Complexity to: Use Complex Collision As Simple

Static_Mesh_Complex_Collision.jpg

This example shows the default behavior for a model that has an opening, neither the projectiles nor the player can pass:

Simple_Collision.gif

In this example collision for the model was set to Use Complex Collision As Simple:

Complex_Collision.gif

 

UE4 – Python – Importing assets

Software:
Unreal Engine 4.20

Untitled-1

Importing assets into a project is done using the import_asset_tasks() function which is a member of the unreal.AssetTools class.
A reference to the AssetTools class is created by calling the get_asset_tools() function which is a member of the unreal.AssetToolHelpers class.
The import_asset_tasks() function requires a list of unreal.AssetImportTask objects as an argument, each unreal.AssetImportTask object in the supplied list represents the import action of a single asset, and contains properties needed for the import operation.
Asset import properties are set using the set_editor_property() function which is called through the AssetImportTask object.
Available asset import properties are listed here:
https://api.unrealengine.com/INT/PythonAPI/class/AssetImportTask.html

In the following example a specified texture file is imported into the project and stored in the Content(Game) > Textures folder.
* If the folder doesn’t exist it will be created.

import unreal
AssetTools = unreal.AssetToolsHelpers.get_asset_tools()
AssetImportTask = unreal.AssetImportTask()
AssetImportTask.set_editor_property('filename', "D:\Wood_Red_A.jpg")
AssetImportTask.set_editor_property('destination_path', '/Game/Textures')
AssetTools.import_asset_tasks([AssetImportTask])

The following example imports all the JPG files from folder: D:\ into the project, stores the new assets in Content(Game)\Textures folder and saves them:

from os import listdir
from os.path import isfile, join
import unreal
dir = "D:\\"
files = [f for f in listdir(dir) if isfile(join(dir, f)) and f[-3:]=='jpg']
AssetTools = unreal.AssetToolsHelpers.get_asset_tools()

import_tasks = []
for f in files:
     print join(dir, f)
     AssetImportTask = unreal.AssetImportTask()
     AssetImportTask.set_editor_property('filename', join(dir, f))
     AssetImportTask.set_editor_property('destination_path', '/Game/Textures')
     AssetImportTask.set_editor_property('save', True)
     import_tasks.append(AssetImportTask)

AssetTools.import_asset_tasks(import_tasks)

* note that when copying and pasting a script from this example, the indentation may not be pasted correctly.

Related:

  1. Get started with Python in UE4
  2. Setting actors locations