Closed stephen-hqxu closed 3 years ago
Hydraulic erosion between chunks is definitely not something easy to implement. In the future we will refer it as free-slip hydraulic erosion.
Here's some dev notes.
When rendered chunks are requested to be loaded, all visible chunks are checked for completeness. If not, for each of those chunks, the program will also check for its surrounded chunks. If any of the surrounded chunk is not found, it will be inserted and computed for heightmap. Whenever it's computable, all neighbour chunks are locked such that no other threads can copy them until it's released, and make a copy of all heightmaps, sent to device.
For all chunks, the simulator will only spawn rain drop at the center chunk, while the neighbour chunks will hold rain drop that flows out of the boundary of the central chunk.
For simplicity, central chunk is contained in neighbour chunks
When we copy neighbour chunks, chunks are aligned linearly, called local index, where the index of the next free-slip chunk starts at the end-index of the previous chunk+1. When chunks are eroded, the rain drop system uses global index system, where index is continuous within a row of a free-slip range, such that the index of the first element of each row of the chunk is the index of the left-hand side element+1.
For more information please refer to the documentation in the source code.
Instead of arranging the chunk into global index system, we use some math formula to convert the index during erosion. To make things more efficient, we pre-compute a lookup table for such index.
Currently we can confirm that water droplet can freely slip to the neighbour chunks. There are a few bugs in the current release, and possible solution for each.
mask = 1
; otherwise mask = 0
.We introduced a new algorithm for generating an interpolation table instead of using the previous interpolation method which used a plenty of branches to check for areas required for interpolation.
Official release will go live soon, hopefully. We are still working on host side codes to ensure data coherence.
The lookup table uses thread ID as index, and lookup for the coordinate (x,z) for required for interpolation. Compared to out old brute-force search method, it not only cuts down the number thread required for such operation, but also utilises all threads.
Checklist Item | Brach Checking (Old) | Specialised Table (New) |
---|---|---|
Type | Conditionals | Mathmatical formulae |
Number of thread lauched | freeslip^2 * dimension^2 | (dimension - 2) (2 freeslip * (freeslip - 1)) + (freeslip - 1)^2 |
Thread utilisation | ~1% depends on freeslip and dimension, smaller utilisation when both are greater | Always 100% |
Data security | Required even more branches to make sure threads don't cross over to other working areas | Interpolation areas are predefined in the table and only simple branches are needed to distribute working threads |
The old algorithm:
if (pixel_requiring_interpolation) {
perform_interpolation();
} else {
return;
// Threads that are not in the interpolation pixel will be killed
}
void perform_interpolation(float* maps) {
// A lot of braches to determine how to do interpolation...
}
We classify interpolation into 3 types:
Patch will not cross over to other patch nor the edge of the freeslip map so the current freeslip chunks can still connect to adjacent area that are not presented. Bits are inserted into the MSB of (x,z) coordinate of the interpolation pixel, and we use combination of both bits to determine what type of interpolation it's, and three simple branches are used for each type.
For more information please refer to the documentation within source code
Current state
Bug caused
Suggestions
Possible implementation