Features and fixes, and curved rivers!
Added a pixel’s worth of ‘overdraw’ to the sides of the heightmap, so that normals can be calculated properly over the full tile, eliminating the tile-edge artifacts like this::
Tile edges are sometimes visible without heightmap overdraw
Fixed up the heightmap pallete to be more than just green, and added lakes.
Lakes promptly returned the bug where underwater pixels closest to a land cell render as lakes when their closest cell isn’t ocean:

Now with lakes! But also with lake bits appearing in the ocean along the coastline
(Looking at how some of these coastal-lake clumps appear to not actually be attached to the land makes me think the TIN rendering is also mixing up the nearest vertex. Something to look into later)
This was fixed by having each heightmap pixel associated with an index into the Triangles array, instead of the cellId of the nearest cell. It requires more lookups but the nearest cellId can be obtained from the Triangles index, and so can the other 2 surrounding vertices, allowing for an underwater pixel to check every vertex of the triangle it’s in to find out whether it’s ocean or lake.
And finally, rivers in TinTileRender2D, and then curved rivers!
Note that now-perfect ocean coastline
Now the curved rivers can create tile-edge misalignment artifacts :(