Skip to content

Commit

Permalink
Terrain: shader support for sampling DEM elevation from float textures
Browse files Browse the repository at this point in the history
Feature is implemented in gl-native first. Since shader code is shared, code here is
not used by gl-js (`TERRAIN_DEM_FLOAT_FORMAT` is not defined).
  • Loading branch information
astojilj committed May 7, 2021
1 parent 64b18a0 commit 2a73031
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 10 deletions.
22 changes: 22 additions & 0 deletions src/shaders/_prelude_terrain.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

#ifdef TERRAIN

#ifdef TERRAIN_DEM_FLOAT_FORMAT
uniform highp sampler2D u_dem;
uniform highp sampler2D u_dem_prev;
#else
uniform sampler2D u_dem;
uniform sampler2D u_dem_prev;
#endif
uniform vec4 u_dem_unpack;
uniform vec2 u_dem_tl;
uniform vec2 u_dem_tl_prev;
Expand All @@ -31,6 +36,10 @@ float decodeElevation(vec4 v) {
}

float currentElevation(vec2 apos) {
#ifdef TERRAIN_DEM_FLOAT_FORMAT
vec2 pos = (u_dem_size * (apos / 8192.0 * u_dem_scale + u_dem_tl) + 1.0) / (u_dem_size + 2.0);
return u_exaggeration * texture2D(u_dem, pos).a;
#else
float dd = 1.0 / (u_dem_size + 2.0);
vec4 r = tileUvToDemSample(apos / 8192.0, u_dem_size, u_dem_scale, u_dem_tl);
vec2 pos = r.xy;
Expand All @@ -45,9 +54,14 @@ float currentElevation(vec2 apos) {
float br = decodeElevation(texture2D(u_dem, pos + vec2(dd, dd)));

return u_exaggeration * mix(mix(tl, tr, f.x), mix(bl, br, f.x), f.y);
#endif
}

float prevElevation(vec2 apos) {
#ifdef TERRAIN_DEM_FLOAT_FORMAT
vec2 pos = (u_dem_size * (apos / 8192.0 * u_dem_scale_prev + u_dem_tl_prev) + 1.0) / (u_dem_size + 2.0);
return u_exaggeration * texture2D(u_dem_prev, pos).a;
#else
float dd = 1.0 / (u_dem_size + 2.0);
vec4 r = tileUvToDemSample(apos / 8192.0, u_dem_size, u_dem_scale_prev, u_dem_tl_prev);
vec2 pos = r.xy;
Expand All @@ -59,6 +73,7 @@ float prevElevation(vec2 apos) {
float br = decodeElevation(texture2D(u_dem_prev, pos + vec2(dd, dd)));

return u_exaggeration * mix(mix(tl, tr, f.x), mix(bl, br, f.x), f.y);
#endif
}

#ifdef TERRAIN_VERTEX_MORPHING
Expand Down Expand Up @@ -106,6 +121,12 @@ float occlusionFade(vec4 frag) {
// This is so that rendering changes are reflected on CPU side for feature querying.

vec4 fourSample(vec2 pos, vec2 off) {
#ifdef TERRAIN_DEM_FLOAT_FORMAT
float tl = texture2D(u_dem, pos).a;
float tr = texture2D(u_dem, pos + vec2(off.x, 0.0)).a;
float bl = texture2D(u_dem, pos + vec2(0.0, off.y)).a;
float br = texture2D(u_dem, pos + off).a;
#else
vec4 demtl = vec4(texture2D(u_dem, pos).xyz * 255.0, -1.0);
float tl = dot(demtl, u_dem_unpack);
vec4 demtr = vec4(texture2D(u_dem, pos + vec2(off.x, 0.0)).xyz * 255.0, -1.0);
Expand All @@ -114,6 +135,7 @@ vec4 fourSample(vec2 pos, vec2 off) {
float bl = dot(dembl, u_dem_unpack);
vec4 dembr = vec4(texture2D(u_dem, pos + off).xyz * 255.0, -1.0);
float br = dot(dembr, u_dem_unpack);
#endif
return vec4(tl, tr, bl, br);
}

Expand Down
24 changes: 14 additions & 10 deletions src/shaders/hillshade_prepare.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ uniform vec2 u_dimension;
uniform float u_zoom;
uniform vec4 u_unpack;

float getElevation(vec2 coord, float bias) {
float getElevation(vec2 coord) {
#ifdef TERRAIN_DEM_FLOAT_FORMAT
return texture2D(u_image, coord).a / 4.0;
#else
// Convert encoded elevation value to meters
vec4 data = texture2D(u_image, coord) * 255.0;
data.a = -1.0;
return dot(data, u_unpack) / 4.0;
#endif
}

void main() {
Expand All @@ -33,15 +37,15 @@ void main() {
// | | | |
// +-----------+

float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y), 0.0);
float b = getElevation(v_pos + vec2(0, -epsilon.y), 0.0);
float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y), 0.0);
float d = getElevation(v_pos + vec2(-epsilon.x, 0), 0.0);
float e = getElevation(v_pos, 0.0);
float f = getElevation(v_pos + vec2(epsilon.x, 0), 0.0);
float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y), 0.0);
float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);
float a = getElevation(v_pos + vec2(-epsilon.x, -epsilon.y));
float b = getElevation(v_pos + vec2(0, -epsilon.y));
float c = getElevation(v_pos + vec2(epsilon.x, -epsilon.y));
float d = getElevation(v_pos + vec2(-epsilon.x, 0));
float e = getElevation(v_pos);
float f = getElevation(v_pos + vec2(epsilon.x, 0));
float g = getElevation(v_pos + vec2(-epsilon.x, epsilon.y));
float h = getElevation(v_pos + vec2(0, epsilon.y));
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y));

// Here we divide the x and y slopes by 8 * pixel size
// where pixel size (aka meters/pixel) is:
Expand Down

0 comments on commit 2a73031

Please sign in to comment.