I ended up using an oldie-but-goodie method based on hemisphere perturbation: you choose a random hemisphere and slightly nudge it outwards and nudge the other hemisphere inwards. Do this a lot of times and you have a reasonable looking planet:
This method has one drawback - one side is the relief of the other, i.e. if one point is above the water level then the opposite point will be underwater. This can be fixed but takes more iterations to look authentic.
All in all, whilst this is certainly not the fastest method, its quick to setup and and easy to understand.
The main issue is that it can take a while to generate the planet and the browser becomes unresponsive during that time. The solution? Move the code across to a web worker. As a result the main code becomes clearer but debugging becomes more of a pain: for debugging web workers I'd recommend chrome - errors in the web worker still display in the console!
The code to generate the planet geometry is in this script. Here I'll go through the main three.js code. Firstly we have the basic three.js set up:
Then set up the textures, the idea is to have a water sphere and a land sphere overlapping so when the land sinks past a certain radius you see the water (i.e. it defines a sea level):
Now all that's left is the land geometry, here's where the web worker comes in:
Then all that's left is to add a slow rotation and it's done.