So, recently I've made this:

Normally, you should see an asteroid-looking ball and an elliptic orbit around it. If you don't see anything, it can be either that the mesh for the ball is still loading, or that your browser doesn't support WebGL2.

If you see the asteroid and the orbit, go ahead and use your mouse to rotate the view, as well as the mouse wheel to zoom out and in.

My goal with this was to learn how to display astrometric data in 3D with WebGL, with the dream of doing something similar to what is done in Kerbal Space Program. I'm far from reaching that dream, but this is a start.

I've made the asteroid model with blender. Starting from an UV-sphere, I just added a displacement modifier controlled by a "clouds" noise texture. I then exported the mesh into glTF using the Khronos Group glTF-Blender-Exporter. Importing the mesh from javascript was quite a hassle, but it was interesting and a good learning experience imho.

One neat trick I've learnt while drawing the orbit is that I don't actually need to feed the shader with any vertices buffer. I could just use the special variable gl_VertexID. The vertex shader looks like this :

#version 300 es

const float tau = 6.283185307179586;

uniform int N;
uniform float a;
uniform float e;
uniform float theta;

uniform mat4 PMatrix;
uniform mat4 VMatrix;
uniform mat4 MMatrix;

out float intensity;

void main() {

   intensity = float(gl_VertexID)/float(N);
   float p = a*(1.0-e*e);
   float phi = theta + tau*intensity;
   gl_Position = PMatrix*VMatrix*MMatrix*vec4( p*cos(phi), p*sin(phi), 0.0, 1.0 + e*cos(phi) );

}
As you can see, there is no "in" variable. All input data is given via uniforms : the only variable that changes along the curve is gl_VertexID.

The ellipse shows a nice intensity gradient, indicating the position of the orbiting body with time. The speed is visibly higher at perigee, and lower at apogee, as expected from basic orbital mechanics. I've tried to made this scientifically accurate, and to do that I had to convert the mean anomaly (which evolves linearly with time) into the true anomaly. After reading the corresponding wikipedia articles, I've learnt that this can be done first by calculating the eccentric anomaly, which is done by solving Kepler's equation. I did it in javascript, by searching the fixed point :

function solveKepler(e, M, N = 20) {
  let E = M;
  for(let i = 0; i< N; i++) E = M + e*Math.sin(E);
  return E;
}
I picked 20 as the default value for the number of iterations for no reason in particular.

I'm happy with this little project, but obviously a lot more must be done to make it useful or fun:

I you feel like helping, feel free to contact me on github or Hackernews (I'm grondilu in both).