I'm working on a game that has a big proc. generated map (10000km by 20000km). The map generation is based on multi-octave perlin noise.
...
vec2 step = vec2(1.3, 1.7);
float n = 0.0;
n += color(uv.xy, t);
n += 0.5 * color(uv.xy * 2.0 - step, t);
n += 0.25 * color(uv.xy * 4.0 - 2.0 * step, t);
n += 0.125 * color(uv.xy * 8.0 - 3.0 * step, t);
n += 0.0625 * color(uv.xy * 16.0 - 4.0 * step, t);
n += 0.03125 * color(uv.xy * 32.0 - 5.0 * step, t);
n += 0.015625 * color(uv.xy * 64.0 - 6.0 * step, t);
n += 0.0078125 * color(uv.xy * 128.0 - 7.0 * step, t);
n += 0.00390625 * color(uv.xy * 256.0 - 8.0 * step, t);
n += (0.00390625 / 2.0) * color(uv.xy * (256.0 * 2.0) - (8.0 * 2.0) * step, t);
n += (0.00390625 / 4.0) * color(uv.xy * (256.0 * 4.0) - (8.0 * 4.0) * step, t);
n += (0.00390625 / 8.0) * color(uv.xy * (256.0 * 8.0) - (8.0 * 8.0) * step, t);
n += (0.00390625 / 16.0) * color(uv.xy * (256.0 * 16.0) - (8.0 * 16.0) * step, t);
n += (0.00390625 / 32.0) * color(uv.xy * (256.0 * 32.0) - (8.0 * 32.0) * step, t);
n += (0.00390625 / 64.0) * color(uv.xy * (256.0 * 64.0) - (8.0 * 64.0) * step, t);
n += (0.00390625 / 128.0) * color(uv.xy * (256.0 * 128.0) - (8.0 * 128.0) * step, t);
n += (0.00390625 / 256.0) * color(uv.xy * (256.0 * 256.0) - (8.0 * 256.0) * step, t);
n += (0.00390625 / 512.0) * color(uv.xy * (256.0 * 512.0) - (8.0 * 512.0) * step, t);
n += (0.00390625 / 1024.0) * color(uv.xy * (256.0 * 1024.0) - (8.0 * 1024.0) * step, t);
...
Showing the noise's code just to give an idea about the size of small values in use.
The goal here is to render the map as topo lines, each one representing small change in terrain height.
This is the current result.
The screenshot below spans for about 19000 kms
This one for about 50 kms (the purple line shows what 1km looks like)
As you can see the closer we get to the ground the less topo lines we get, which is not what I want. My goal is to have high precision topo lines even at small scales like few kilometers.
I use the following GLSL code to detect edges:
const float STEPS = 10000000.;
const mat3 EDGE_KERNEL = mat3(
-1, -1, -1,
-1, 8, -1,
-1, -1, -1
);
float discretize(float value, float offset) {
return floor(value * float(STEPS) + offset) / float(STEPS);
}
float tex(vec2 p) {
return discretize(texture2D(heightmap, p).x, .5);
}
...
//outlines
float edge = 0.;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
vec2 offset = vec2(float(j - 1), float(i - 1)) / resolution.xy;
vec2 texCoord = uv + offset;
edge += 1. / tex(texCoord) * EDGE_KERNEL[j][i];
}
}
vec3 outlineMask = edge > 0.01 ? vec3(0.) : vec3(1.);
...
Unfortunately, I cannot provide the full code or even stripped one since it's pretty hard to strip this code, but I'm ready to provide any details necessary.
The question is why the edges are not being detected for small float differences. I tried different values in the edge > 0.01
condition, but no good results there either.
Did I hit the float precision limit, or is it my noise (it looks like it has enough octaves to give the actual differences to those height), or is it the edge detection algo I use?