Reusable 3D Earth globe widget (pure OCaml + WebGL)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(ocaml-globe): dim Earth when coverage is active, spotlight effect

Earth.draw now takes ?dim parameter (0.0–1.0) to control base
brightness. When orbits+coverage are shown, Earth renders at ~20-25%
brightness. Coverage additive blending then lights up the areas under
satellite footprints back to full brightness — only visible parts of
the Earth glow, everything else stays dark.

The visual flow:
1. Dim Earth dots (u_dim uniform in fragment shader)
2. Grid overlay (unaffected)
3. Coverage filled triangles (additive blend brightens underlying dots)
4. Net result: dark globe with bright spotlights under each satellite

+33 -16
+7 -2
demo/main.ml
··· 250 250 Globe_webgl.Stars.draw gl stars ~projection ~view; 251 251 Gl.enable gl Gl.depth_test 252 252 end; 253 - if Signal.get show_dots then 254 - Globe_webgl.Earth.draw gl earth ~projection ~view; 253 + if Signal.get show_dots then begin 254 + let dim = 255 + if Signal.get show_coverage && Signal.get show_orbits then 0.2 256 + else 1.0 257 + in 258 + Globe_webgl.Earth.draw gl earth ~projection ~view ~dim () 259 + end; 255 260 if Signal.get show_grid then 256 261 Globe_webgl.Grid.draw gl !grid ~projection ~view 257 262 ~color:(0.1, 0.3, 0.5) ~alpha:0.25 ();
+12 -10
webgl/earth.ml
··· 15 15 u_projection : Gl.uniform_location; 16 16 u_view : Gl.uniform_location; 17 17 u_point_size : Gl.uniform_location; 18 + u_dim : Gl.uniform_location; 18 19 } 19 20 20 21 let v ?(num_points = 30000) gl = ··· 43 44 Gl.enable_vertex_attrib_array gl 1; 44 45 Gl.vertex_attrib_pointer gl 1 1 Gl.float false 16 12; 45 46 Gl.bind_vertex_array gl None; 47 + let u name = Gl.get_uniform_location gl prog (Jstr.of_string name) in 46 48 { 47 49 prog; 48 50 vao; 49 51 num_points = n; 50 - u_projection = 51 - Gl.get_uniform_location gl prog (Jstr.of_string "u_projection"); 52 - u_view = Gl.get_uniform_location gl prog (Jstr.of_string "u_view"); 53 - u_point_size = 54 - Gl.get_uniform_location gl prog (Jstr.of_string "u_point_size"); 52 + u_projection = u "u_projection"; 53 + u_view = u "u_view"; 54 + u_point_size = u "u_point_size"; 55 + u_dim = u "u_dim"; 55 56 } 56 57 57 - let draw gl t ~projection ~view = 58 + let draw gl t ~projection ~view ?(dim = 1.0) () = 58 59 Gl.use_program gl t.prog; 59 - let proj_arr = Tarray.of_float_array Tarray.Float32 projection in 60 - let view_arr = Tarray.of_float_array Tarray.Float32 view in 61 - Gl.uniform_matrix4fv gl t.u_projection false proj_arr; 62 - Gl.uniform_matrix4fv gl t.u_view false view_arr; 60 + Gl.uniform_matrix4fv gl t.u_projection false 61 + (Tarray.of_float_array Tarray.Float32 projection); 62 + Gl.uniform_matrix4fv gl t.u_view false 63 + (Tarray.of_float_array Tarray.Float32 view); 63 64 Gl.uniform1f gl t.u_point_size 3.5; 65 + Gl.uniform1f gl t.u_dim dim; 64 66 Gl.bind_vertex_array gl (Some t.vao); 65 67 Gl.draw_arrays gl Gl.points 0 t.num_points; 66 68 Gl.bind_vertex_array gl None
+11 -2
webgl/earth.mli
··· 8 8 (default 30000). *) 9 9 10 10 val draw : 11 - Brr_canvas.Gl.t -> t -> projection:float array -> view:float array -> unit 12 - (** [draw gl t ~projection ~view] renders the Earth dot cloud. *) 11 + Brr_canvas.Gl.t -> 12 + t -> 13 + projection:float array -> 14 + view:float array -> 15 + ?dim:float -> 16 + unit -> 17 + unit 18 + (** [draw gl t ~projection ~view ?dim ()] renders the Earth dot cloud. 19 + [dim] (default 1.0) controls overall brightness: 1.0 = full, 20 + 0.0 = invisible. Use ~0.25 when coverage is shown so that only 21 + areas under satellite footprints appear bright via additive blending. *)
+3 -2
webgl/shader.ml
··· 51 51 precision highp float; 52 52 53 53 in float v_brightness; 54 + uniform float u_dim; 54 55 out vec4 fragColor; 55 56 56 57 void main() { 57 58 float d = distance(gl_PointCoord, vec2(0.5)); 58 59 if (d > 0.5) discard; 59 60 float alpha = smoothstep(0.5, 0.1, d); 60 - // Dark ocean blue → bright cyan coastline 61 61 vec3 color = mix(vec3(0.03, 0.10, 0.25), vec3(0.35, 0.90, 1.0), v_brightness); 62 - fragColor = vec4(color, alpha * (0.3 + v_brightness * 0.7)); 62 + // u_dim: 1.0 = full brightness, 0.0 = completely dark 63 + fragColor = vec4(color * u_dim, alpha * (0.3 + v_brightness * 0.7) * u_dim); 63 64 } 64 65 |} 65 66