As part of Cubiquity's ProcessVDB tool I actually wrote a heightmap converter, and was amazed at just how difficult it was. Converting a heightmap to a smooth volume seemed trivial but I spent a long time thinking about it.
Firstly, forget about different materials for now and just use one. That way you only have to think in terms of a single density per voxel. Now the problem is that you have height at each point and a voxel is either above or below it - this is a binary decision which means you end up setting each voxel to be either solid or empty.
As I recall, I tried instead setting the density of the voxel relative to the distance between the voxel and the top of the column. I then scaled it by some factor(s) which I found by trial-and-error. You can see the code here:
https://bitbucket.org/volumesoffun/cubi ... ap.cpp-135I think you can ignore this part of the code (it's just stuff for materials?):
Code:
if (materialSet.data > 135)
{
materialSet.data <<= 8;
}
though I'm a little hazy to be honest. Most usefully, I found it was helpful to scale the image down from a higher-resolution version of the heightmap. You might be able to avoid this, because your procedural data is effectively infinite resolution anyway. Also I had to start with ints, where as you will be starting with floats which should be easier.
To be honest, this was one of the problems which made me realise just how difficult and unintuitive density fields were, and why I decided to just focus on tiny cubes for Cubiquity 2!