Note : Godot 3.2.1, Blender 2.82, Gimp 2.10, Affinity Designer 1.8.2.
In the game, I want to have a couple of stone tablets (or wooden panels) with carved text.
My initial idea was to create a text object in blender, and then use a boolean to create inset text on a cube or a plane.
My second idea involved faking the text with a texture made in Gimp.
Either way, it involved watching a lot of tutorials, a lot of experimenting, and also luck (to stumble across the vital tidbits of information that were still missing).
Creating text objects in Blender is easy : add a text object to the scene, go into edit mode, select all, and start typing your text.
Notice that the text object has no depth (eg. in front view) . To make it a true 3d object, use the extrude option in the geometry section.
You can also add some bevel to the text, if you like.
Notice that the width of the characters changes (increases) as you add bevel. You can compensate for that by applying an equal, but negative, amount to the offset :
Note : if you want to use a non-default font (one that didn't come
with Windows - eg. a font downloaded from a website), you'll need to save it in a location that's
-NOT- the default Windows location (c:∖windows∖fonts) !
Blender does not seem to detect newly installed fonts in the default location (even after a restart) ...
To use the text object with a boolean modifier, it needs to be converted to a mesh object first (right click with the mouse to get to the context menu).
If you toggle into edit mode, you'll see that the mesh is a bit of a mess (lots of thin triangles). This makes it difficult to do anything else with it (bevel, subdivide, ...).
It might be a good idea at this point to enable the 'Mesh : 3D Print Toolbox' addon. The addon is meant to indicate areas of trouble (= need to fix first) for when you're planning to 3d print. The addon will show up in the menu on the right side of the 3d view (when you press 'N').
This is the result I got :
In edit mode, the summary has buttons that can show you the areas that need to be fixed.
One thing you'll definitely need to do before using this text mesh, is to
-remove doubles- (in 'vertex select mode' > vertex menu
> merge vertices > by distance) !
You can also try some of the options in the 'cleanup' item in the Mesh menu ...
Now, we can finally use a boolean modifier : add a cube to the scene, scale it so that it is big enough for the text, apply scale, position the mesh in wireframe mode, add a boolean modifier, select the text mesh, and apply the modifier on the cube mesh.
You can now move or delete the original text mesh ; it's no longer needed.
Depending on the font used, you might get a decent result (after cleanup).
Furthermore, if the text is short, and you only need a small number of text objects in your game, the total face count per text object might be ok (I had 800 faces without the bevel). But it's not ideal.
So, after some thinking, I decided to be clever, and bake a normal map of the cube mesh with the inset text ...
Flat shading, and faces that are parallel and perpendicular to the baking plane do not work (well) in normal maps !
I could try to add a bevel to the edges where the text cuts into to top plane of the cube,
but it is a lot of work (because of the (thin) triangles) and the result isn't that good.
I also tried using a 'remesh' modifier (generates a new mesh topology based on quads) after the text object is converted into a mesh object, but the result was similar.
1) 2d :
I first tried creating a 3d effect (text inset) in Gimp and Affinity Designer.
This is what I managed after quite a bit of experimentation (I'm not very good at art) :
I started with the text in black, on the stone background texture.
I then duplicated the background layer and masked it with the text (the black text is now filled with the background texture - something new I learned =) ). Finally, I fiddled around with the bevel/emboss, outer, and inner shadow settings.
Next, in Blender, I created the mesh I want the text to appear on, and uv-unwrapped it. I then exported (saved) the resulting uv (uv > export uv layout) and opened it in Affinity Designer. I then scaled and rotated the texture I created in Affinity Designer, so that the text showed up on the correct face of the uv map.
Finally, I exported the resulting image (without the uv layer visible !) and imported it back
into Blender, to be used in the stone cube mesh material.
I also created a normal map with the NVIDEA Texture Tools software.
And that's it.
All in all, a pretty simple procedure, although it is a bit random how I got to the relief profile of the text in Affinity Designer. I also need to be a bit careful to make sure that the background stone texture has a similar scaling in all the text meshes I need to make.
2) 3d :
The second approach is based on 2 great tutorials by Chipp Walters (see list below).
In the first tutorial, he shows how to add multiple decals (eg. text) to a wooden crate. In the second tutorial, he shows how to combine all the shader info into a simpler material that can be imported into a game engine.
This is what my result looked like :
You start by uv unwrapping the mesh for the stone, and then adding the stone texture to its material.
You can add some roughness by using the color output from the texture and plugging it into the roughness setting of the Principled BSDF shader (through a color ramp so you can adjust the amount of roughness; and also whether you want the light or the dark material to be rough).
You can also add normal map info, again by using the color output from the texture and plugging it into the normal setting of the BSDF node (through a bump node, so lightness is converted into height).
Next, it is time to add the text. I prepared a texture in Gimp (white text on a transparent background). This texture could combine all the text that I want to use in the game.
In Blender, switch to the UV Editor and create a new uv map in slot 2 (I named it 'decal_lumos_200') :
Unwrap the stone cube again.
This is so that you can place/scale the text independently from the stone background texture.
Switch to the Shading Editor, add a Texture node and a Color MixRGB node. Attach the stone texture
to one color slot, and an Input RGB node to the second color slot. The alpha
output from the text texture goes into the 'fac' input of the MixRGB node. (If you see that the stone texture
is masked by the text (the stone texture only shows up in the text), you need to switch the 2 color slots.)
This setup is so that we can give the text (white) any color we like.
Very important : add an Input UV map node, and connect it to the 'vector' input of the text texture. Select the name of the second uv map from the dropdown.
Note : I have selected the nodes for the text and created a group with them (node > create group). This makes the shader node tree look a bit more organized.
You can toggle in and out of a group with the 'tab' key.
Finally, since I want the text to be inset, I added a second 'bump' node behind the first one. The alpha from the text texture node is connected to the height input of the bump node. The 'invert' option is checked to create the inset effect.
And that's that.
If you want the inset to be shiny, you need to use a second shader, the Glossy BSDF (else the stone texture would be glossy as well). The result :
The group now looks like this :
And that's that.
But there is a problem with this setup : getting the material into Godot (which I didn't manage to do) !
Fortunately, the tutorial had a second part that solved exactly this problem ! The idea is to combine all nodes so that you end up with just 1 diffuse texture and 1 normal map.
And how do you do that ?
It is actually quite simple.
First, you need to create a third uv map (in the UV Editor) and unwrap the mesh again.
Next, you add a new texture node ; the texture node format is the one you want to use in your game (eg. 1024x1024 px ; no alpha).
Select the mesh, select the texture node, and switch to the Render Properties tab. Select the Cycles renderer, and bake the 'diffuse' with only the Color pass selected.
Save the baked image, add a second texture node (non-color), select the mesh, select the second texture node, and bake the 'normal' (default settings). Save the baked texture.
Create a new material for the stone cube, using the 2 baked textures. Don't forget to use the 3rd uv map !
You now have a simple material that you can import into the Godot engine.
... Or not.
If you try to import the new material into Godot, you'll notice something strange. It is as if Godot is ignoring the uv map !
As it turns out, that is exactly what is happening.
Even though our new material uses only 1 uv map, Blender exports all 3 ! And Godot can only deal with 2 uv maps ...
So, we need to get rid of the 2 uv maps that we no longer need !
And finally ! Here is the stone cube with inset text inside Godot :
Note : The stone on the left was exported with glTF, the one on the right with FBX.
Even though I prefer to use glTF (out of principle), I think FBX actuall looks slightly better ...
Note : I also considered making a simple stone plaque mesh, with
a text plane in front of it. The plane would have a simple transparent material.
Even though this seems the easiest way to get text on the props, I decided against it because, as you know, transparent materials are more expensive than opaque materials ...
So. Now it's time for some well-deserved R&R !