Blender to Unreal Engine tips

Software:
Blender 2.9 | Unreal Engine 4.25

The following is a list of guidelines for preparation and export of 3D content from Blender to Unreal Engine 4 via the FBX file format.

Disclaimer:
This is not a formal specification.
It’s a list of tips I found to work well in my own experience.
* Some of the issues listed here may have already been solved


Blender Scene and model settings:

System units in Blender:
Define the scene units in Blender as:
Metric unit with 0.01 scale (centimeters)
And model your content correctly using centimeter units.
* Modeling in 1 meter units may seem to be imported correctly into UE4 but will cause unsolvable problems like a skeletal mesh physics asset having incorrect auto-generated shapes, a problem that in my experience can’t be fixed manually.

Transform:
Model your model in Blender facing the -Y world axis, +Z obviously being up (obviously for Blender).
* This way the model is aligned to Blender’s views so the front view displays the model’s front etc.
Make sure to apply your model’s transformations before export.

Armatures:
Make sure the Armature object isn’t named “Armature”.
naming or leaving the Blender skeleton named “Armature” will cause the UE4 importer to fail due to “multiple roots”.
* Also remember some weird related bug with animation scale incorrectly imported, but can’t confirm this now..
No need for a dedicated root bone in the hierarchy. the Armature object is the root of the bone hierarchy.
* See export option below

Texture baking:
Set the normal map’s green channel to -Y.
* This is not critical at all because if baked as +Y it can easily be fixed in UE4.

Metadata:
Blender custom properties import as UE4 asset metadata that can be read by editor scripts for automation purposes.
* See export option below


FBX Blender export and UE4 import settings:

I recommend saving an FBX export preset with these settings.

Optional:
I prefer the export settings to include only selected objects.
* It’s more efficient for me to select the specifics objects I want to export into a single FBX file prior to export, than to delete all the temp / reference / draft objects from the scene.
If you want to export Blender custom properties with to the FBX check the “Custom Properties” option

Axes:
Blender’s native model/world orientation is model’s forward facing the -Y axis, left side facing +X and of-course up facing +Z.
UE4’s native model/world orientation is model’s forward facing the +X axis, left side facing -Y and up facing +Z.
There are axis settings in Blender’s FBX export module, that theoretically, should be set like this:

However, in tests I did, The axis settings made no difference when importing to UE4, even when setting intentionally incorrect upside-down axes.
Maybe the FBX exporter writes these settings to metadata that the UE4 importer doesn’t read..
From my experience, what’s important is to orient the model correctly in Blender (see above), apply the transformations,
And in the UE4 import menu, check the “Force Front XAxis” option:

Geometry:
Make sure either “Edge” or “Face” is chosen in the “Smoothing” option to import the mesh’s smooth shading correctly ans avoid a smoothing groups warning on import:

Optional:
Depending on how much control you need over the mesh’s tangent space,
You may want to check the “Tangent Space” export option,
This will make Blender export the full tangent space to the FBX and make UE4 read it from FBX instead of generate it automatically.
* For this option to be supported, the mesh geometry must have only triangle or quad polys.
In the UE4 import settings, choose the “Import Normals and Tangents” option in “Normal Import Method”:

Armature:
Set “Armature FBXNode Type” to “Root”.
Uncheck the “Add Leaf Bones” option to avoid adding unneeded end bones.
Set bones primary axis as X, and secondary axis as -Z.

Animation:
Uncheck “All Actions” to avoid exporting actions that don’t actually belong to the skeleton.
* Un-related animations in the FBX can also corrupt the character rest pose in UE.
The “NLA Strips” option is useful for exporting a library of animations with the skeleton.
* In Blender’s NLA editor, activate the actions you want exported to the FBX.


Related:
3ds max & V-Ray to UE4 Datasmith workflow

A collection of Python snippets for 3D

If you’re interested in taking the first step into Python for 3D software,
Or simply would like to browse some script examples, your welcome to visit my Gist page,
It contains a useful library of Python code example for Blender, Maya, 3ds max and Unreal engine:
https://gist.github.com/CGLion

Blender Python – Reading mesh UV data

Software:
Blender 2.83

Simple example code for reading mesh UV data.

Link to this code snippet on gist

Note that there are typically many more mesh loops than vertices.
*Unless the case is a primitive undivided plane..

import bpy
access mesh data:
obj = bpy.context.active_object
mesh_data = obj.data
mesh_loops = mesh_data.loops
uv_index = 0
iterate teh mesh loops:
for lp in mesh_loops:
    # access uv loop:
    uv_loop = mesh_data.uv_layers[uv_index].data[lp.index]
    uv_coords = uv_loop.uv
    print('vert: {}, U: {}, V: {}'.format(lp.vertex_index,      uv_coords[0], uv_coords[1]))

Blender – Python – Access animated vertices data

Software:
Blender 2.83

The following is simple example of reading a mesh’s animated vertices data.

This example code gist

Note that accessing an model’s animated vertex locations requires reading the model’s evaluated (deformed) mesh state per frame.
For that reason a new bmesh object is initiated per each frame with the the model’s updated dependency graph.

import bpy
import bmesh
obj = bpy.context.active_object
frames = range(0,10)
get the object's evaluated dependency graph:
depgraph = bpy.context.evaluated_depsgraph_get()
iterate animation frames:
for f in frames:
    bpy.context.scene.frame_set(f)
    # define new bmesh object:
    bm = bmesh.new()
    bm.verts.ensure_lookup_table()
    # read the evaluated mesh data into the bmesh   object:
    bm.from_object( obj, depgraph )
    # iterate the bmesh verts:
    for i, v in enumerate(bm.verts):
        print("frame: {}, vert: {}, location: {}".format(f, i, v.co))

Advanced car-paint OSL shader

cglSurfaceCarPaint is an advanced car-paint OSL shader, free to download from CG-Lion studio’s website.

The cglSurfaceCarPaint car-paint material combines 3 layers:
Base: A blend of diffuse/metallic shading with a view-angle color mix
Metallic flakes: Distance blended procedural metallic flakes
Clear coat: Glossy clear coat layer with built-in procedural bump irregularity
And has been tested with:
Blender & Cycles
Maya & Arnold
3ds max & V-Ray

Download and more info

Getting started with OSL shaders

 

Blender 2.83 – OSL bug and fix

Software:
Blender 2.83

I recently found that some of my OSL shaders don’t work in Blender 2.83.
More specifically, shaders compiled with Blender 2.83 had their microfacet bsdf not recognized by the renderer and return 0.
* Shaders that were compiled by previous versions did work.
Looking into the problem I found that the OSL source files that ship with Blender 2.83 are significantly different than the files shipped with previous versions.

Simple fix:
Copy the stdosl.h and oslutil.h from Blender 2.82 to 2.83.
On Windows these files are found in this folder:
C:\Program Files\Blender Foundation\Blender 2.83\2.83\scripts\addons\cycles\shader

* I’m not suggesting to download the files strait from ImageWorks GitHub because I’m not sure the ones that ship with Blender & Cycles are not modified.

I have reported the bug here.

Related:
Using OSL Shaders in Blender & Cycles

Using OSL Shaders in Blender & Cycles

Software:
Blender 2.82 | Cycles

The Cycles render engine in Blender has a very convenient OSL Shader development and usage workflow.
Shaders can be both loaded from external files or written and compiled directly inside Blender.

Before you begin:
Make sure your Blender scene is set to use the Cycles render engine, in CPU rendering mode, and also check the option Open Shading Language:
Annotation 2020-05-28 165830

 

To write an OSL shader in Blender:

  1. Write your shader code in Blender‘s Text Editor:
    Annotation 2020-05-28 173405
  2. In your object’s material shader graph (Shader Editor view),
    Create a Script node:
    Annotation 2020-05-28 170331
  3. Set the Script node‘s mode to Internal,
    And select your shader’s text from the Script node‘s source drop-down:
    Annotation 2020-05-28 170711
  4. If the shader compiles successfully, the Script node will display its input and output parameters, and you can connect it’s output to an appropriate input in your shading graph.
    * If your shader is a material (color closure) connect it directly to the Material Output node’s Surface input, is it’s a volume to the Volume input, or if its a texture to other material inputs as needed.
    Annotation 2020-05-28 171419
  5. If the shader code contains errors, it will fail to compile, and you’l be able to read the error messages in Blender‘s System Console window:
    Annotation 2020-05-28 172423
  6. After fixing errors or updating the shader’s code, press the Script Noe Update button on the Script node to re-compile the shader:
    Annotation 2020-05-28 172735

 

Loading an external OSL shader into Cycles:

Exactly the same workflow described in the previous section, except setting the Script node‘s mode to External and either typing a path to the shader file in the Script node or pressing the little folder button to locate it using the file browser:Annotation 2020-05-28 173159

 

Related:

  1. OSL read-list
  2. What are OSL shaders?
  3. Using OSL shaders in Arnold for Maya
  4. Using OSL shaders in V-ray for 3ds max
  5. Writing a basic OSL color shader
  6. Blender 2.83 OSL bug & fix

Blender – Adding a texture to an Area Light

Software:
Blender 2.82

Adding a texture to an area light can make it produce softer and more detailed highlights and an overall more organic lighting effect.

Note:
Since an Area light in Blender isn’t rendered as an actual mesh object with UV coordinates, it’s texture coordinates are parametric (see below).

Adding a texture to an Area Light:

  1. In the Area Light properties click the Use Nodes button (see image A) to initiate its node graph and allow texturing it.
  2. In the Shader Editor view (with the light selected), drop your texture to the light’s node graph and connect it to the light’s Emission node’s Color input. (see image B)
  3. Create a new Input > Geometry node, and connect it’s Parametric output to the Image Texture’s Vector input. (see image B)

A. Without a texture the Area light produces a hard flat highlight:
a

B. With the vignette texture, the Area light now has a more subtle organic effect:
* The Emission node’s Strength was increased in this case to compensate for the lower light output with the texture.
b
Related posts:

  1. Cycles Area Light pleasent surprise
  2. Cycles Area Light shader visibility

Blender – Basic time-dependent animation driver examples

Software:
Blender 2.82

To setup a time-dependent Driver in Blender, simply use the built-in frame variable.
In this example the expression:

sin(frame)

Set as a Z axis location driver for the cube causes it to oscillate up and down:

frame_driver

Changing the expression to:

sin( frame * 0.1 ) * 2

Causes the motion to be twice as high and 10X slower:

frame_driver2

 

In this example, the expression:

( pow( -1 ,  floor( frame / 30 ) )  *  0.5 ) + 0.5

Set to the cube’s Emission shader’s Strength attribute causes it to alternate between values of 0 and 1 every second (30 frames in this case):

frame_driver3

 

Related:
Blender – Create constraints quickly

Python for Blender – Batch renaming objects

Software:
Blender 2.8 | Python 3.7

Some useful short Python snippets for batch re-naming objects in Blender:

  1. Remove last 4 characters from selected object names:
    import bpy
    objects = bpy.context.selected_objects
    for o in objects:
        o.name = o.name[:-4]

    Annotation 2020-04-23 202028

  2. Rename all selected objects to a set base name followed by a 3 digit numeric suffix:
    import bpy
    objects = bpy.context.selected_objects
    for (i,o) in enumerate(objects):
         o.name = "some_base_name_{:03d}".format(i)

    Annotation 2020-04-23 202718

  3. Prefix all selected objects name with their Blender data type like renaming “SomeModel” to “MESH_SomeModel” or for example:
    import bpy
    objects = bpy.context.selected_objects
    for (i,o) in enumerate(objects):
         o.name = "{}_{}".format(o.type,o.name)

    Annotation 2020-04-23 203345

 

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

Note:
Blender 2.8 has a robust batch renaming utility that is invoked by pressing Ctrl + F2 so we don’t have to write scripts to do batch renaming of objects:

Annotation 2020-04-24 174503


Related:

Python for Blender – Accessing Mesh Triangles