Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

WebGL effort

Information, contacts and source code for ports to Linux, Windows, etc.

Moderators: winston, another_commander

grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Well, something very confusing happened. As I was switching to kilometer for the unit base, I divided the vertex coordinates for the mesh of the Cobra by one thousand, and I was hoping to see no difference whatsoever. I mean, normally when you shrink something, it should look exactly the same as long as you look it from closer, right?

Well, apparently not. As I got closer to the model, it got clipped before it could look "big" on the screen :

Image

After some thought I suspected it was because of the 1 in the (w, w) term of my projection matrix. So I switched it to zero and that made things better, but not much.

There's something I don't quite get here. I'll need to think about it before going further.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: WebGL effort

Post by cim »

What you're running into here looks like the near plane/far plane/z-buffer issue. http://www.sjbaker.org/steve/omniv/love ... uffer.html is an old article (it talks about 16/24 bit buffers when the choice on modern hardware tends to be 24/32) but still a good one.

Put the scale in km, and the near plane at 1km cuts off the ship as you approach.
Put the scale in m, and the resolution near the far plane is too poor to draw a planet-sized object properly.

You also may get problems when exceeding ~10^8/10^9 units due to OpenGL using single-precision floats for positions and transformation.

In Oolite these issues are mitigated by:
- using double-precision floats for almost everything until they are finally converted down to pass to OpenGL (JS by default uses double-precision floating-point for its numbers, so this you probably already have)
- having two separate rendering passes - one for everything within a hundred metres of the camera, and one for everything outside it. There are various complicated issues with how objects on the boundary of the rendering are managed which still aren't completely solved in Oolite.
- drawing the planets at 1% of their real size
User avatar
Norby
---- E L I T E ----
---- E L I T E ----
Posts: 2577
Joined: Mon May 20, 2013 9:53 pm
Location: Budapest, Hungary (Mainly Agricultural Democracy, TL10)
Contact:

Re: WebGL effort

Post by Norby »

cim wrote:
drawing the planets at 1% of their real size
In [wiki]FarPlanets[/wiki] I used realistic planet sizes but got similar problems exactly from the size of the Mars so I choosed to stay within this size.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

cim wrote:
- having two separate rendering passes - one for everything within a hundred metres of the camera, and one for everything outside it. There are various complicated issues with how objects on the boundary of the rendering are managed which still aren't completely solved in Oolite.
I should try something like that. I'm wondering if I could not treat ships and celestial bodies differently. With different shaders and projection matrices, for instance.
- drawing the planets at 1% of their real size
I really would like to avoid doing that.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

I kind of got something working :

Image

I pushed the result, it's here until I make other changes.

As you can see here mars is in real size with a radius of 3.4Mm. It is seen from 30Mm.

The line :

Code: Select all

    mars.near = 1000
gives it a near field which is used by the camera to display it with a near clip distance of one kilometer (I switched back to using the meter as a unit). I could probably go with more, I'll see if it's needed. In any case if I don't put this line I get the ugly artifacts mentioned earlier.

For other objects (which have no near field), the default near distance is 0.5m.

The critical question is : does that messes up with the z-buffer order? The risk is that at some point the cobra is masked by mars while it's supposed to be in front of it. I think as long as the cobra remains far away from mars (that is much further than its near clip distance), it's fine. It will need to be tested more, though.
User avatar
Stardust
Above Average
Above Average
Posts: 31
Joined: Sat Jan 05, 2013 6:06 pm
Location: Cologne, Germany
Contact:

Re: WebGL effort

Post by Stardust »

In Alite, I ran across the same problem, and in the end, I copied the approach from "Celestia" (http://www.shatters.net/celestia/): They use "depth buckets", which is essentially similar to cim's idea. You order your objects by z and iterate over them (farthest away from the camera first). Now, you add objects to your current "bucket", while the distance spanned by all objects in the bucket is smaller than X. If the new object is so far away from the last object that the radius of the bucket would be bigger than X, you start a new bucket.

When rendering the buckets, you clear your depth buffer before each bucket. In Alite, the partition implementation looks like that (slightly simplified; note that "allMyObjects" are already sorted along the z axis (= "distance" to the camera)):

Code: Select all

private final void partitionDepths(final List <DepthBucket> sortedObjectsToDraw) {
    DepthBucket currentBucket = null;
    DepthBucket behind = new DepthBucket();
    behind.near = -1;
    behind.far = -1;
		
    for (Object p: allMyObjects) {
        float dist = p.distance; // Can be negative, relative to camera
        float size = p.getBoundingSphereRadius();
        if (dist < -size) {
            behind.sortedObjects.add(p);
            continue;
        }
        float near = dist - size;
        float far = dist + size;
        if (near < 1.0f && far > 1.0f) {
            near = 1.0f;
        }
        if (currentBucket == null) {					
            currentBucket = new DepthBucket();
            currentBucket.near = near;
            currentBucket.far = far;
            currentBucket.sortedObjects.add(p);		
        } else {					
            if (far > currentBucket.near) {
                currentBucket.sortedObjects.add(p);
                if (currentBucket.near > near) {
                    currentBucket.near = near;
                }
                if (currentBucket.far < far) {
                    currentBucket.far = far;
                }
         } else {
             sortedObjectsToDraw.add(currentBucket);
             float newFar = currentBucket.near;
             currentBucket = new DepthBucket();
             currentBucket.near = near;
             currentBucket.far = newFar;
             currentBucket.sortedObjects.add(p.object);						
         }					
    }

    if (currentBucket != null) {
        sortedObjectsToDraw.add(currentBucket);
    }
    if (behind.sortedObjects.size() > 0) {
        sortedObjectsToDraw.add(behind);
    }
}
And for rendering:

Code: Select all

for (DepthBucket bucket: buckets) {			
    GLES11.glClear(GLES11.GL_DEPTH_BUFFER_BIT);	
    for (AliteObject go: bucket.sortedObjects) {
       go.render();
    }
}
Maybe this helps a little...
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Hello,

so as you have probably noticed I lost interest in this project lately. It was getting seriously tedious and the limitations of WebGL were frustrating as it was clear I would never get as good a result as in the native builds of Oolite.

However, apparently WebGL 2.0 is coming:

Image

It's already available on recent builds of Firefox and chrome, but unfortunately not on linux so I can't try it yet. I suspect it will come soon though.

Then it should hopefully be possible to import more things from the initial code (shaders, textures...) without having to tweak them all the time. And we could have as good of a graphical result, or possibly even better (with HDR maybe, since it's mentioned in slide 11, section sRGB).

It's a long way, but it may lead somewhere one day. Wouldn't it be nice to run Oolite in the browser, without having to install anything?
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Hello,

I figured how to import Oolite models in blender (importing models was quite a hassle and a major reason I had given up on this project lately).

Image

I used two repos : oolite-assets is for the wavefront models (.obj) that can be directly imported from blender. oolite-binary-resources is for the textures, which
for some reason are not in oolite-assets. After the import the path to the textures must be manually modified.

Then a few tweaks are necessary : adding an other instance of the texture for each material, setting one of them to use the non-alpha channels for color diffusion, and the other one to use the alpha-channel for light emission.

I'm hoping that once the model is in blender, I should be able to export it in the new GL Transmission Format from Khronos. Normally that should allow for an easy import from a WebGL framework such as THREE (but others should work too).
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

I'm struggling with converting the mesh into something that can be easily used in webgl, but meanwhile, I've fiddled a bit with CSS to create a welcome screen:

http://grondilu.github.io/oolite/

Warning : music is auto-playing and can be loud.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6573
Joined: Wed Feb 28, 2007 7:54 am

Re: WebGL effort

Post by another_commander »

Hey, it looks very nice. Keep it up!
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

I finally managed to import the glTF format. I wanted to do it without any framework (I'm not too happy with anyone I've tried) so it was kind of hard.

http://grondilu.github.io/oolite/test-cobra3.html

glTF is a very interesting format. For one, it's designed by the Khronos group, the creators and maintainers of WebGL itself, so it's supposed to be the best there is for webGL. It's also a binary format (at least for the main part, that is geometries and stuff), so that means it should be fast to download and load in the graphics card memory.

To do this first test I modified Khronos's official webgl tutorial:

https://www.khronos.org/webgl/wiki/Tutorial

So now that it works with a simple ship (or a least one of its sub-entities), I just need to clear things and integrate it for further processing. My next goal is to do the "ship library" page.

Also I haven't tried yet to use the alpha channel : I can only make it work in blender so far, but now that I get how it works, I should be able to write the correct shader and use it eventually.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

This thing kept me awake tonight. Couldn't figure out why the alpha channel would not show up.

Turns out it was the blender exporter that erased it :/

It works now : http://grondilu.github.io/oolite/test-cobra3.html

Sorry I did not kept the earlier version of this page, so if you visit this thread in a far future, you may be confused. But hey, this is just a test page, it is not supposed to stay alive young anyway.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Quick update.

I am now more or less comfortable converting models from OBJ to glTF and displaying them in WebGL.

I have updated the welcome page (again : sound warning) to display a few more ships.

http://grondilu.github.io/oolite/

Image

I'm not sure I'll do a proper library page though. I don't know quite which layout to pick and it's not
technically interesting anyway. So I'll stick with allowing the client to pick a ship to display from a select input on the front page.

I put all the models in a single blender files, which I also export in a single glTF (and its companion binary .bin file).

I also now use crossOrigin sources for textures and music. That is, I directly use the oolite github repos for them.

From now I'll be working on implementing the docking mini-game again. I did it before but it was with a very different code base
so it will require some work.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Hello,

just to tell you I've lost a bit of motivation lately, so I will probably not go back to this for a bit. The perspective of setting the document layout, dealing with various UI and so on look more and more tedious as I think about it.

I will eventually go back to it, but not in the short term.

The code is freely available though if anyone wants to look at it, and I'm willing to answer questions.

bye
User avatar
Griff
Oolite 2 Art Director
Oolite 2 Art Director
Posts: 2479
Joined: Fri Jul 14, 2006 12:29 pm
Location: Probably hugging his Air Fryer

Re: WebGL effort

Post by Griff »

I just want to wish you the best of luck with future projects grondilu, you've done some really awesome work here that hopefully you can apply to future stuff :)
Post Reply