1
$\begingroup$

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.

enter image description here

This is the current result.

The screenshot below spans for about 19000 kmsenter image description here

This one for about 50 kms (the purple line shows what 1km looks like)

enter image description here

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?

$\endgroup$

1 Answer 1

0
$\begingroup$

Alright, so the issue was that the shader is a multipass one, so before detecting edges I exported my noise into a 2d sampler at which point it seems it loses some (a lot of) precision.

So I went to packing/unpacking float (e.g. as described here https://stackoverflow.com/questions/13005391/loss-of-precision-in-glsl-fragment-shader).

With this approach I was able to get this much of topo lines (again, purple line shows 1 km): enter image description here

There are some artifacts here, but I'm sure it's just a matter of coefficients.

$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.