layout(std140) uniform ColorReliefDrawableUBO { highp mat4 u_matrix; }; layout(std140) uniform ColorReliefTilePropsUBO { highp vec4 u_unpack; highp vec2 u_dimension; highp int u_color_ramp_size; highp float pad_tile0; }; layout(std140) uniform ColorReliefEvaluatedPropsUBO { highp float u_opacity; highp float pad_eval0; highp float pad_eval1; highp float pad_eval2; }; uniform sampler2D u_image; uniform sampler2D u_elevation_stops; uniform sampler2D u_color_stops; in vec2 v_pos; float getElevation(vec2 coord) { // Convert encoded elevation value to meters vec4 data = texture(u_image, coord) * 255.0; data.a = -1.0; return dot(data, u_unpack); } float getElevationStop(int stop) { // Elevation stops are plain float values, not terrain-RGB encoded float x = (float(stop) + 0.5) / float(u_color_ramp_size); return texture(u_elevation_stops, vec2(x, 0.5)).r; } vec4 getColorStop(int stop) { float x = (float(stop) + 0.5) / float(u_color_ramp_size); return texture(u_color_stops, vec2(x, 0.5)); } void main() { float el = getElevation(v_pos); // Binary search for color stops int r = (u_color_ramp_size - 1); int l = 0; while (r - l > 1) { int m = (r + l) / 2; float el_m = getElevationStop(m); if (el < el_m) { r = m; } else { l = m; } } // Get elevation values for interpolation float el_l = getElevationStop(l); float el_r = getElevationStop(r); // Get colors for interpolation vec4 color_l = getColorStop(l); vec4 color_r = getColorStop(r); // Interpolate between the two colors // Guard against division by zero when el_r == el_l float denom = el_r - el_l; float t = (abs(denom) < 0.0001) ? 0.0 : clamp((el - el_l) / denom, 0.0, 1.0); fragColor = u_opacity * mix(color_l, color_r, t); #ifdef OVERDRAW_INSPECTOR fragColor = vec4(1.0); #endif }