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

Configure Feed

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

refactor: move orbit rendering to ocaml-globe, remove orbis library

- Move orbit line + satellite dot rendering to Globe_webgl.Orbit
(reusable for any app showing orbits on the globe)
- Remove orbis/lib entirely (math, sphere, coord, orbit all extracted)
- orbis is now a pure web executable with no library
- Clean up shader_app.ml (only conjunction shaders remain)

+234
+192
webgl/orbit.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Thomas Gazagnaire. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + (** Orbit line and satellite dot rendering. 7 + 8 + Draws orbit paths as GL_LINE_STRIP with dual-pass glow effect, 9 + and satellite positions as GL_POINTS with radial falloff. *) 10 + 11 + open Brr 12 + open Brr_canvas 13 + 14 + (* --- Shaders --- *) 15 + 16 + let line_vertex = 17 + {|#version 300 es 18 + precision highp float; 19 + layout(location = 0) in vec3 a_position; 20 + uniform mat4 u_projection; 21 + uniform mat4 u_view; 22 + void main() { 23 + gl_Position = u_projection * u_view * vec4(a_position, 1.0); 24 + } 25 + |} 26 + 27 + let line_fragment = 28 + {|#version 300 es 29 + precision highp float; 30 + uniform vec3 u_color; 31 + uniform float u_alpha; 32 + out vec4 fragColor; 33 + void main() { 34 + fragColor = vec4(u_color, u_alpha); 35 + } 36 + |} 37 + 38 + let dot_vertex = 39 + {|#version 300 es 40 + precision highp float; 41 + layout(location = 0) in vec3 a_position; 42 + uniform mat4 u_projection; 43 + uniform mat4 u_view; 44 + uniform float u_point_size; 45 + void main() { 46 + gl_Position = u_projection * u_view * vec4(a_position, 1.0); 47 + gl_PointSize = u_point_size; 48 + } 49 + |} 50 + 51 + let dot_fragment = 52 + {|#version 300 es 53 + precision highp float; 54 + uniform vec3 u_color; 55 + out vec4 fragColor; 56 + void main() { 57 + float d = distance(gl_PointCoord, vec2(0.5)); 58 + if (d > 0.5) discard; 59 + float glow = smoothstep(0.5, 0.0, d); 60 + fragColor = vec4(u_color * glow, glow); 61 + } 62 + |} 63 + 64 + (* --- Types --- *) 65 + 66 + type color = float * float * float 67 + 68 + type line = { 69 + vao : Gl.vertex_array_object; 70 + num_points : int; 71 + color : color; 72 + } 73 + 74 + type dot = { 75 + pos : Globe.Math.Vec3.t; 76 + color : color; 77 + } 78 + 79 + type t = { 80 + line_prog : Gl.program; 81 + line_u_proj : Gl.uniform_location; 82 + line_u_view : Gl.uniform_location; 83 + line_u_color : Gl.uniform_location; 84 + line_u_alpha : Gl.uniform_location; 85 + dot_prog : Gl.program; 86 + dot_u_proj : Gl.uniform_location; 87 + dot_u_view : Gl.uniform_location; 88 + dot_u_color : Gl.uniform_location; 89 + dot_u_size : Gl.uniform_location; 90 + mutable lines : line list; 91 + dot_vao : Gl.vertex_array_object; 92 + dot_vbo : Gl.buffer; 93 + } 94 + 95 + (* --- API --- *) 96 + 97 + let v gl = 98 + let line_prog = 99 + Shader.program gl ~vert:line_vertex ~frag:line_fragment 100 + in 101 + let dot_prog = 102 + Shader.program gl ~vert:dot_vertex ~frag:dot_fragment 103 + in 104 + let dot_vao = Gl.create_vertex_array gl in 105 + let dot_vbo = Gl.create_buffer gl in 106 + Gl.bind_vertex_array gl (Some dot_vao); 107 + Gl.bind_buffer gl Gl.array_buffer (Some dot_vbo); 108 + Gl.buffer_data_size gl Gl.array_buffer 12 Gl.dynamic_draw; 109 + Gl.enable_vertex_attrib_array gl 0; 110 + Gl.vertex_attrib_pointer gl 0 3 Gl.float false 0 0; 111 + Gl.bind_vertex_array gl None; 112 + let u name prog = Gl.get_uniform_location gl prog (Jstr.of_string name) in 113 + { 114 + line_prog; 115 + line_u_proj = u "u_projection" line_prog; 116 + line_u_view = u "u_view" line_prog; 117 + line_u_color = u "u_color" line_prog; 118 + line_u_alpha = u "u_alpha" line_prog; 119 + dot_prog; 120 + dot_u_proj = u "u_projection" dot_prog; 121 + dot_u_view = u "u_view" dot_prog; 122 + dot_u_color = u "u_color" dot_prog; 123 + dot_u_size = u "u_point_size" dot_prog; 124 + lines = []; 125 + dot_vao; 126 + dot_vbo; 127 + } 128 + 129 + let add_line gl t positions ~color = 130 + let valid = 131 + Array.to_list positions |> List.filter_map Fun.id |> Array.of_list 132 + in 133 + let n = Array.length valid in 134 + if n > 0 then begin 135 + let data = Array.make (n * 3) 0. in 136 + Array.iteri 137 + (fun i (v : Globe.Math.Vec3.t) -> 138 + data.(i * 3) <- v.x; 139 + data.((i * 3) + 1) <- v.y; 140 + data.((i * 3) + 2) <- v.z) 141 + valid; 142 + let buf = Tarray.of_float_array Tarray.Float32 data in 143 + let vao = Gl.create_vertex_array gl in 144 + Gl.bind_vertex_array gl (Some vao); 145 + let vbo = Gl.create_buffer gl in 146 + Gl.bind_buffer gl Gl.array_buffer (Some vbo); 147 + Gl.buffer_data gl Gl.array_buffer buf Gl.static_draw; 148 + Gl.enable_vertex_attrib_array gl 0; 149 + Gl.vertex_attrib_pointer gl 0 3 Gl.float false 0 0; 150 + Gl.bind_vertex_array gl None; 151 + t.lines <- { vao; num_points = n; color } :: t.lines 152 + end 153 + 154 + let clear_lines t = t.lines <- [] 155 + 156 + let draw gl t ~projection ~view ~dots = 157 + let proj = Tarray.of_float_array Tarray.Float32 projection in 158 + let vw = Tarray.of_float_array Tarray.Float32 view in 159 + (* Orbit lines: dual-pass glow *) 160 + Gl.use_program gl t.line_prog; 161 + Gl.uniform_matrix4fv gl t.line_u_proj false proj; 162 + Gl.uniform_matrix4fv gl t.line_u_view false vw; 163 + List.iter 164 + (fun (l : line) -> 165 + let r, g, b = l.color in 166 + Gl.uniform3f gl t.line_u_color r g b; 167 + Gl.uniform1f gl t.line_u_alpha 0.4; 168 + Gl.bind_vertex_array gl (Some l.vao); 169 + Gl.draw_arrays gl Gl.line_strip 0 l.num_points; 170 + Gl.uniform1f gl t.line_u_alpha 1.0; 171 + Gl.draw_arrays gl Gl.line_strip 0 l.num_points; 172 + Gl.bind_vertex_array gl None) 173 + t.lines; 174 + (* Satellite dots *) 175 + Gl.use_program gl t.dot_prog; 176 + Gl.uniform_matrix4fv gl t.dot_u_proj false proj; 177 + Gl.uniform_matrix4fv gl t.dot_u_view false vw; 178 + Gl.uniform1f gl t.dot_u_size 8.0; 179 + List.iter 180 + (fun (d : dot) -> 181 + let buf = 182 + Tarray.of_float_array Tarray.Float32 183 + [| d.pos.x; d.pos.y; d.pos.z |] 184 + in 185 + Gl.bind_buffer gl Gl.array_buffer (Some t.dot_vbo); 186 + Gl.buffer_data gl Gl.array_buffer buf Gl.dynamic_draw; 187 + let r, g, b = d.color in 188 + Gl.uniform3f gl t.dot_u_color r g b; 189 + Gl.bind_vertex_array gl (Some t.dot_vao); 190 + Gl.draw_arrays gl Gl.points 0 1; 191 + Gl.bind_vertex_array gl None) 192 + dots
+42
webgl/orbit.mli
··· 1 + (** Orbit line and satellite dot rendering. 2 + 3 + Generic renderer for colored orbit paths (GL_LINE_STRIP with 4 + dual-pass glow) and position dots (GL_POINTS with radial falloff). 5 + Reusable for any app that shows orbits on the globe. *) 6 + 7 + type color = float * float * float 8 + (** RGB color, each component in [0, 1]. *) 9 + 10 + type dot = { 11 + pos : Globe.Math.Vec3.t; 12 + color : color; 13 + } 14 + (** A satellite position dot. *) 15 + 16 + type t 17 + (** Opaque orbit renderer state. *) 18 + 19 + val v : Brr_canvas.Gl.t -> t 20 + (** [v gl] creates an orbit renderer. *) 21 + 22 + val add_line : 23 + Brr_canvas.Gl.t -> 24 + t -> 25 + Globe.Math.Vec3.t option array -> 26 + color:color -> 27 + unit 28 + (** [add_line gl t positions ~color] adds an orbit line from an array 29 + of positions (None entries are skipped). *) 30 + 31 + val clear_lines : t -> unit 32 + (** [clear_lines t] removes all orbit lines. *) 33 + 34 + val draw : 35 + Brr_canvas.Gl.t -> 36 + t -> 37 + projection:float array -> 38 + view:float array -> 39 + dots:dot list -> 40 + unit 41 + (** [draw gl t ~projection ~view ~dots] renders all orbit lines and 42 + satellite position dots. *)