Skip to content
kripken edited this page Apr 2, 2012 · 20 revisions

WebGL Rendering

We will manually port the rendering code to use a subset of OpenGL we can easily translate to WebGL.

Things to take into account

  • See here for ehsan's demo of his work on the Emscripten OpenGL ES 2.0 to WebGL bindings.
  • See the WebGL docs zfor differences between WebGL and OpenGL ES 2.0, and here for general OpenGL/OpenGL ES 2.0 differences. For GLSL differences between OpenGL ES 2.0/WebGL and desktop OpenGL, see here.
  • WebGL calls cost more than OpenGL native calls, because of JS<->native code communication. We might need to optimize code to make fewer calls, or avoid certain types of rendering. For example, if some visual effect (explosions? water?) constantly uploads vertex data each frame, that might be slow. We should check if it is, because it might not be, but if it is then a simple optimization might be to previously upload all the needed values, etc.
  • It is not trivial to detect that we are generating a WebGL-friendly subset of OpenGL. For example, glVertexAttribPointer receives a last param that can be a raw pointer into client data - invalid for WebGL - or a byte offset into a bound buffer - valid for WebGL. The problem is that the invalid case can fail silently (if another buffer was bound before, then the raw clientside pointer is interpreted as an offset into it, likely going out of bounds and returning 0's). (This happened in the very first OpenGL ES 2.0 example in the OpenGL ES 2.0 Programming Guide!)
  • However, webgl.verbose in Firefox does warn about many of these issues. Extremely useful against silent failures!
  • glDrawElements is another function where the last parameter can be a pointer to clientside data, or an index, and we need just an index.
  • We should, as early as possible, make a list of crucial OpenGL extensions that Sauerbraten depends on for performance and visual quality so that we can ask the browser people to add them. The list might include
  • Occlusion queries?
  • Antialiasing?

Coding approach

  • We should use #ifdefs when we need to not run some GL code and instead run new GL code that we add, so that it is easy to build for either mode.
  • Alternatively it could be done at runtime, through a variable check (like forceglsl works now, it could be forcepureglsl perhaps). This might add runtime overhead though.

Documentation

  • One of our goals is to investigate how porting a GL game to the web goes, so we should document our progress here, pointing out what we had to do, problem areas, etc., to help other porting projects in the future.

Alternatives

  • Mozilla is also planning to write a general OpenGL-to-WebGL conversion layer. This would be something that emulates the fixed-function pipeline in software. Existing solutions exist (Mandreel, TitaniumGL, VMWare's GL virutalization) so this is feasible. However it adds overhead, and for that reason in this project we are focusing on manual rewriting of the GL rendering code. Also, the general conversion layer will take several months and we don't want to wait on it.
  • When the general conversion layer is done, it will be interesting to benchmark it against the manual coding we are doing here, to get an idea of how much slower the conversion is.

Additional issues with WebGL in browsers

  • Browsers can't modify the screen resolution. So if we render to the whole screen, we will use that resolution, which might be slower than a lower resolution. Should investigate the possibility to render to a smaller size and blow it up to the actual resolution, but that might look horrible.
Clone this wiki locally