Height Lab - Height and Normal Map Generator

Hi everyone! I wrote a tool called Height Lab that lets you create square height maps and normal maps from expressions. I mostly wrote it for Technical Artists so that the textures could be used in shaders, but it can also be good for creating height and normal maps for other things like: brushes, height maps for terrain, and particles.

Here’s the blurb from Steam:

Height Lab is a developer tool that makes it possible to visualize and create height maps and normal maps using math. Its layout is like a paint program, but the layers are expressions instead of images. Once a height map is designed, both height maps and normal maps can be saved as: JPG, PNG, TGA, EXR16, EXR32, EXR16SRGB, or EXR32SRGB.

Height Lab is good for procedurally creating height maps, normal maps, brushes (normal and height), particles, and masks. These are good for: games, simulators, 2D and 3D paint programs, shader effects, and various unique transition effects.

FEATURES

  • Laid out similar to a paint program.
  • Preview changes live.
  • Quality of life Undo/Redo and Shortcut Keys.
  • Includes examples.
  • Expressions can be separated into layers.
  • Layers can be enabled/disabled, and soloed for single layer viewing.
  • Multiple height maps can be designed in a single project.
  • Custom variables can be created and used in expressions.
  • Built in functions for: sphere, cone, pyramid, and sweep.
  • Viewport area for previewing the height map in 2D and 3D.
  • Height map can be animated in both u and v directions.
  • Height map can be “dissolved” from top to bottom.
  • Supported output types are: height map (including normalized) and normal map (GL and/or D3D).
  • Outputs can be saved as: JPG, PNG, TGA, EXR16, EXR32, EXR16SRGB, or EXR32SRGB.
  • The output size can be powers of two from 32x32 all the way up to 4096x4096.

You can get it from Steam here:
https://store.steampowered.com/app/2810890/Height_Lab/

If you have any feedback, please post either here or directly in the Height Lab Discussion on Steam.

Thanks, and I hope you find it really useful!

1 Like





Height Lab is 50% off until July 11th!

In a nutshell, here’s what it can do…

Hand write an expression and visualize it in the viewport.
Expression

When the height map or normal map is complete, export it to: JPG, PNG, TGA, EXR16, EXR32, EXR16SRGB, or EXR32SRGB.

There are also built in shapes to use as a base for other more complicated expressions.
Shapes

Enjoy!

I posted a link to this on the company slack, interested to see how the discussion goes

1 Like

Got a new update for you! I’ve overhauled the UI so that properties can be edited in a single location. This has opened up the interface so it doesn’t seem so crammed.

I’ve also revamped how Outputs are added. Now you just click a button for Height or Normal, and their properties show up in the new properties panel where you can edit them.
Outputs

Properties for Height. Now normalizing the height is just a checkbox.
HeightProperties

Properties for Normal. Now you can flip any axis. All off is for GL, and enabling Y would be D3D.
NormalProperties

I hope you enjoy the new changes!

Does this use surface gradients for the final normal generation? or is it closer to a traditional height map to normal algorithn?

Honestly, that is a new term for me. I just looked it up, and apparently Unity has a surfgrad workflow I’ve never heard of before.

As far as Height Lab goes, it uses the classic Sobel filter. The underlying height map is made up of 32 bit floats. After the height map renders on the CPU, the result is copied to a render texture so the shaders can take it from there.

I will continue to look into this surface gradient stuff as it relates to GPU rendering. Are there any benefits to it over Sobel that you know of? Maybe point me in the right direction?

The great thing about surface gradients is the composition workflow – you can layer different frequencies without constantly renormalizing . Also normals at the visible horizon are not lost they way they often are with conventional tangent space normals.

Good reference here if you don’t mind the math : https://jcgt.org/published/0009/03/04/paper.pdf

1 Like

Thank you, that was good info, and I might need it to know how to proceed with future updates of Height Lab.

From what I understand of that paper, he’s blending bump maps samples from different uv sets, and then using the TBN matrices (created dynamically?) to reconstruct normals to render surface detail. The part that is like Height Lab is the blending of the bump maps.

Height Lab also does blending (not really, but I’ll explain later), but the blending happens “before” a normal is created, just like with the gradient shader.

I want to say that you could use Height Lab to generate the bump maps that could be used by the gradient shader. You wouldn’t really use the normals generated by Height Lab.

One thing to note would be that Height Lab does not generate normals from geometry. The geometry you see in Height Lab is a subdivided mesh, and it uses the height map to displace the vertices to give it depth.

Normals are constructed from the height map using the Sobel filter. The Sobel filter takes the difference between adjacent left and right heights for x, and adjacent top and bottom heights for y. It looks like this in the shader:

n = normalize(float3((left - right), (up - down), 1.0f))

Height Lab has the appearance of blending, but all it does is combine expressions. The expression takes (x, y), some built in variables, and user variables as inputs. If you’re familiar with writing HLSL or GLSL, it’s like that. In a fragment program you sample textures with (u, v), in Height Lab an expression is sampled with (x, y).

I’m not sure if that answers your question exactly, but I hope that clarifies what Height Lab is, and what it does. If I am way off, I’m still curious as to what angle you are coming from so that I can understand you better.

Here’s the most complicated expression I’ve made so far:

(((((
(noisep(x+xo,y+yo,rep/2^((1.0)-1),rep/2^((1.0)-1))/(2^(((7.0)-1)-(1.0))))+
(noisep(x+xo,y+yo,rep/2^((2.0)-1),rep/2^((2.0)-1))/(2^(((7.0)-1)-(2.0)))))+
(noisep(x+xo,y+yo,rep/2^((3.0)-1),rep/2^((3.0)-1))/(2^(((7.0)-1)-(3.0)))))+
(noisep(x+xo,y+yo,rep/2^((4.0)-1),rep/2^((4.0)-1))/(2^(((7.0)-1)-(4.0)))))+
(noisep(x+xo,y+yo,rep/2^((5.0)-1),rep/2^((5.0)-1))/(2^(((7.0)-1)-(5.0)))))+
(noisep(x+xo,y+yo,rep/2^((6.0)-1),rep/2^((6.0)-1))/(2^(((7.0)-1)-(6.0)))))/
(1/((7.0))*((7.0)-1)+1)

The result:

Height Lab is on sale again at 50% off…and…

I’ve updated both the Height Lab page and the Steam store page so they show mostly height map images instead of normal maps. I also go into more detail about how height maps can be combined to make more complicated height maps.

The reason I was showing normal maps all over the place was because shallow heights are hard to see in the image - basically black to a very dark grey. With normal maps it’s easy to see the curves.