Logo 3.5Cats_AndHalfAFish



June 30, 2020 Shade, different workflows for banners
Of the heavy kind.

Note : Godot 3.2.1, Blender 2.83, Affinity 1.8.3.

Intro ramble.

This week, I have been working on setting up a workflow to create banners for my game. 'Banners' as in 'the things you see hanging on the walls of old castles'. The heavy, carpetty stuff :

Godot (editor) : banner.
This is what this post is about. (Godot editor view).

It has been fun to try and figure this one out, even though I have been plagued by gremlins and have lost a lot of time. But that's what game development is like, I guess.

You may have noticed that I'm using Affinity software in this workflow. I picked it up during the lockdown, mostly because I was looking for something to replace Adobe Flash (or 'Animate' as it is now called).
Flash was wonderful software for creating vector art, and animating and scripting it. I made my very first game with it. I was 36 at the time. 🙀

The Affinity software seems to be quite different from Flash. It has a rather strange mix of vector and bitmap workflows, and I feel a bit lost in it, at the moment.

Anyway. Let's get started .

Workflow : mesh creation.

The first thing to do is, of course, create a model in Blender.
Since this banner is supposed to be rather heavy, I first modeled it as a plane, and then gave it some thickness with the 'solidify' modifier.

Blender : banner mesh.
Blender : banner mesh.

Next step : uv unwrapping (don't forget to 'apply scale' before you do this !).
I decided to use a 1024x1024 texture (without alpha) even though I was a bit worried about the resolution (woven fabric). But since I don't mind having the same look for the back and front of the banner, I could cheat a little bit :

Blender : uv mapping.
Blender : uv mapping.

This layout is basically the same thing as having the 2 uv islands positioned perfectly on top of each other. But with this difference : if you later on bake for instance an ao map, the ao information of the second island will not overwrite the info of the 1st ; instead, it is discarded.
Be careful to position the islands perfectly on top of each other, and then move the backside island exactly 1 unit on the x- or y-axis.

One thing that I did wrong with the uv map here, is that I didn't straighten out the edges of the islands. You can see this better in the ao bake below : the bottom corners of the banner are curved, and that will cause a small problem when I texture the mesh.

The final thing I did in Blender, was to bake an ao map. This is something I (very recently) picked up from Markus Wolfram (see list at the bottom of this post).

Blender : ao map.
Blender : ao map.

As you can see, mine isn't anything special, and I only have information for the front part of the banner. But that's ok.

Some things to pay attention to : I changed the margin for the ao map bake to 2px. This means that the information written to the ao map will be 2px larger in every direction than it actually is (you can easily see this when you overlay the uv).
In my model, it's not important (I could have set the margin to 0), but in general, it is used to help prevent artifacts around seams (see Blender documentation).

Blender : ao map margin.
Blender : ao map margin.

If you decide to use a margin, you also need to take that into account when you uv unwrap ('margin' or 'spacing') ! There has to be enough space between the islands to account for the ao bake margin.
Notice that with my banner model, the uv islands do not come up all the way to the borders.

Workflow : diffuse texture.

The texture that I wanted to create, had a red background of woven fabric. It also had a golden symbol and borders.

This is where I have been using Affinity Designer, but of course, the same things can be done with Gimp or any other similar software.

I started by opening up the ao map (1024x1024 px). I then added another layer containing the fabric texture I wanted to use for the background (1000x1000 px, right kind of design but wrong color).
Usually, when the texture is too small, you need to tile it (repeat it on both axes). Gimp has some good functionality for making a texture tileable : filters > map > tile seamless.
Fortunately, the fabric texture didn't need to be tiled since it still looked good stretched.

Next, I duplicated the fabric layer and adjust the color to red (from gold) : with the duplicated layer selected, click the 'layer' menu > new adjustment > recolor.

Affinity Designer : recoloring the fabric.
Affinity Designer : recoloring the fabric.

To create the print that I wanted to appear on the fabric background (a symbol and some borders), I used the ao layer as a guide.
Using vector images comes in very handy here : no need to worry about resolutions while scaling and editing !

The final step was to combine all the different layers using masking. This is ridiculously easy in AD (and I finally understand how it works !).
To 'cut out' the correct banner shape from the red background, I 'masked' the red fabric layer with the ao layer : put the ao layer on top of the red fabric > right-click the ao layer > 'mask to below'.

Affinity Designer : masking the background.
Affinity Designer : masked background.
Affinity Designer : masked background.

The same thing was done for the symbol and the borders layers, using the golden fabric.
And since the borders were created going outside the ao map, I masked them with the ao layer as well.

If you want the information from the ao map to be visible on the diffuse texture, you can make a copy of the ao layer and put it above all the other layers, with the blend mode set to 'multiply' :

Affinity Designer : final texture (with and without ao).
Affinity Designer : final texture (with and without ao).
Affinity Designer : final texture (closeup).
Affinity Designer : final texture (closeup).

Workflow : normal texture.

I'm still struggling a bit with creating and using non-diffuse textures. I did a lot of reading and a lot of experimenting, and this is a summary of what I think I've learned so far.
There are 2 sections. The first section is about the simplest (and probably least correct) way of obtaining a normal map for the banner. The second part takes a look at 'a better way' to do things.

1) The simplest way.

I found a 'normal map' option in Gimp ! It is hiding in the 'filters' dropdown 'generic' section.
This is the result of the filter used on the diffuse texture created in the previous section (default settings) :

Gimp : normal map.
Gimp : normal map.

The alternative : NVIDEA Texture Tool with default settings :

NVIDEA : normal map.
NVIDEA : normal map.

Both of them seem to work in Godot, although the map that was generated by Gimp seems to result in a bit of a 'rougher' texture (see below).

2) A better way.

What I want to accomplish here, is to combine 2 normal maps. The first map is the one for the fabric texture, the second one is for the inset golden print.

The first normal map was easy to obtain.
Just drag the original diffuse fabric texture into the NVIDEA Texture Tools application, and set the 'image type' to 'normal map : tangent space'. Adjust the strength with the 'scale' slider in the 'height generation' section.

The second normal map was a bit of trial and error.
I ended up using a black and white 1024x1024 px image, with black for the inset print and white for the rest. This is what the NVIDEA Tool made of it :

Black and white image for normal map 2.
Normal map 2 (from a black and white image).

Combining the two normal maps posed a bit of a problem.
In the end, I found 2 different ways to combine normal maps in Photoshop. Even now, I don't really understand how they work ... but they work, so ...

Method 1 : I've seen this method being referred to as 'the lazy way'. It's quick and dirty, but the result is ok.

1) Put the layer with the detail normal map above the more general one.
2) Set the blend mode of the top layer to 'overlay'.

Method 2 : this method seems to be 'the correct way'. It prevents the loss of information from the blue channel of the composite normal map (which is a problem with the overlay method). There's a clear explanation and 'how to' in a blog by 'Nightshade' on ModDB (see list below).

The workflow described for PS can easily be copied over to Affinity Photo (not : Affinity Design), with some minor tweaks (my own 'translation' - this could be wrong) :

1) PS : Image > Adjustments > Levels
→ AP : select a layer > switch to the 'adjustment' tab next to the 'layers' tab > Levels. Press the 'merge' button (top right) once the 3 channels have been adjusted.
2) PS : Levels menu : 'Set the Red input to 128 1 255'
→ AP : Levels popup > pick 'red' from the 'master' dropdown > drag the 'black level' to 50%.
3) PS : Levels menu : 'Set the Red input to 0 1 127'
→ AP : Levels popup > pick 'red' from the 'master' dropdown > drag the 'white level' to 50%.
4) PS : Image > Adjustments > Channel Mixer
→ AP : switch to the 'adjustment' tab next to the 'layers' tab (with a layer selected) > Channel Mixer. Press the 'merge' button (top right) once the 3 channels have been adjusted.
5) PS : Channel Mixer menu : 'Set the red channel to -100% RED, and its constant to +50%'
→ AP : Channel Mixer popup > select 'red' from the dropdown > drag the 'red' slider to -100% and the 'offset' slider to +50%.
6) PS : Layers : 'set the layer blend mode to "Subtract"'
→ AP : Layers > blend mode : subtract
7) PS : Layers : 'set the layer blend mode to "Linear Dodge: Add"'
→ AP : Layers > blend mode : add (?).

A comparison of the 2 methods :

Normal maps obtained with methods 1 (left - lazy) and 2.
Normal maps obtained with methods 1 (left - lazy) and 2.
Blue channel info with methods 1 (left - lazy) and 2.
Blue channel info with methods 1 (left - lazy) and 2.

And here are the 4 banners side by side in Godot :

Godot : diffuse + normal map (quick - Gimp).
Godot : diffuse + normal map (quick - Gimp ; scale -1.5).
Godot : diffuse + normal map (quick - NVIDEA).
Godot : diffuse + normal map (quick - NVIDEA ; scale -1.5).
Godot : diffuse + normal map (composite : overlay).
Godot : diffuse + normal map (composite : overlay ; scale +1.5).
Godot : diffuse + normal map (composite : correct way).
Godot : diffuse + normal map (composite : correct way ; scale +1.5).

Notice that the 2 maps generated from the diffuse texture need to have the normal map scale set to -1.5. The 2 composite maps on the other hand, need a setting of +1.5.
I'm not sure why that is ...

Workflow : rougness and metallic textures.

I'm not sure the banner needs maps for this. But just to go through the motions ...
The metal texture is mostly black, but with some dark gray for the gold print.
The roughness texture is the inverted metal texture (so mostly white, with some pale grey).

I can't really see a difference in-game though. I think these maps might be more useful for hard or flat(tish) surfaces.

Workflow : Silly mistakes.

First silly mistake (that took me a silly amount of time to figure out) :

Banner in editor vs. in game.
Banner in the editor (left) vs. in the game.

I had no error messages, and the textures had loaded correctly (you can still see them if you squint a bit).

So, what was going on ?
Well, once I (finally) realized that I had set the editor to display in unshaded mode (models are not affected by lamps), I knew that the problem had to do with normals.

As it turns out, I had been experimenting with the glTF export settings about a week ago, but had forgotten all about that because most of my time since was spent on texturing (outside of Blender).
Apparently, you still need to export normals from Blender, even if you use a normal map ('normal map textures -modify- the existing mesh normals' ?) ...

Blender : glTF export settings.
Blender : glTF export settings.

Second mistake, in the category 'Floors are just as important as walls' :

This banner is really starting to look good !
This banner is really starting to look good !


Relevant information.

  • 'Godot Engine' - mw design.
    A peek into Markus Wolfram's mind while he's creating some beautiful stuff for Godot.
  • 'Photoshop: Combining normal maps.' - Nightshade.
  • 'Tutorial: How to combine two normal maps using Photoshop' - Jacob Anderson.
    Same information as Nightshade blog, but as YouTube video.
  • 'Affinity Photo : macros' - Affinity Photo documentation.
    The tutorial by Nighshade mentions creating a macro to speed things up.
  • 'Affinity : color management' - Affinity documentation.
    It is important that textures have an sRGB color profile for use in Godot.
  • 'sRGB Color Space questions' - Affinity forum.
  • 'Godot : importing images' - Godot documentation.
    Check these settings on textures used for 3d scenes !
  • 'Blender : Color vs. Non-Color data' - StackExchange.
    Clear explanation of what it means and when to use it.
  • 'Bit Depth & How Compression Affects Normal Maps' - Jonathan Lampel on CGCookie.com.
  • 'Resources : tutorials' - Ben Cloward.
    Info about normal maps.
  • 'Normals vs Normal maps' - Game Development.
  • 'Normals and Normal Map Theory' - Alvar.
  • 'Tutorial: How Normal Maps Work & Baking Process' - Carlos Lemos.
  • Affinity Designer : if you accidentally set a stroke on an object, and you want the stroke removed without a change in the overal size of the object ... There is a way !
    Black arrow (move tool) > select the layer with the stroke > layer menu (top) > expand stroke. The stroke has now been changed into a curve.
    To join the curve and the fill : white arrow (node tool) > shift select the curve and the fill > layer menu (top > create compound (can be undone).