Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Precision issue with r49 #1898

Closed
kovleouf opened this Issue · 24 comments

4 participants

kovleouf Mr.doob AlteredQualia gero3
kovleouf

I updated my Three lib to r49 but i'm dealing with many precision issue when rendering my old scene (it was working fine with r48).

The issues only occur when rendering far away from the world origin (further than 2 000 000 on some axis).

1st : my ground is formed of many Meshs built with PlaneGeometry and i now have some 1 pixel width holes between my meshs when moving the camera.

2nd : i'm dealing with a strong precision issue (>50 world unit error) when using projector and Matrix / Vector multiplication.

I tried to revert the Matrix optimization stuff but i didn't manage to get it working with all the function change in this release :-/

Mr.doob
Owner

Can you share ascreenshot?

kovleouf

i'm sorry but i can't show more than this partial screenshot (with a red background to see the holes):

http://i40.servimg.com/u/f40/13/20/89/97/screen10.jpg

These holes are not always visible depending on the camera distance/angle.
The camer target is x = 538711, y = 5742553, when i move near the world origin there is no issue.

NB: i didn't change the webgl renderer precision (still highp)

AlteredQualia

Hmmm, this is interesting / bad.

I wonder if this is just some bug introduced by optimizations or there is something inherently different when doing math directly on typed arrays instead of JS floats (if I remember well, these are rather large, not sure if types match).

BTW precision specifier shouldn't matter on desktop GPUs, it's supposed to be just for mobile ones.

Edit: Yup, found it. JS numbers are 64 bit floats while new optimized Matrix4 uses 32 bit float typed arrays.

http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference

I wonder how much of performance gain actually came from this instead of from typed arrays themselves.

@mrdoob I don't think we should switch to Float64Array everywhere but maybe it could be optional?

@kovleouf Could you try to change these lines to use Float64Array to see if it helps for you?

https://github.com/mrdoob/three.js/blob/master/src/core/Matrix4.js#L15
https://github.com/mrdoob/three.js/blob/master/src/core/Matrix3.js#L7

kovleouf

Using Float64Array lead to this error on 1st frame :

Uncaught TypeError: Type error in WebGLRenderer.js:4754

gero3

I beleive support is missing for Float64Array in firefox

kovleouf

I'm using Chrome 18.0

AlteredQualia

Ah no, I think it's because now we send Matrix4's typed arrays directly to WebGL and there it must be 32 bit floats again.

Hmmm, you would need to cast these somehow.

@gero3 Firefox supports Float64Array. It's in typed array specs and I just checked in console ;)

gero3

Ah I'll look into it, then.
It will probably not get much slower by changing the matrixes and casting it later. But I have to look into it.

AlteredQualia

Hmmm, Float32Array vs Float64Array performance seems quite surprising:

http://jsperf.com/float32array-vs-float64array/2

May be worth to try 64 bit floats?

gero3

gero3@d0d472d

This is my first try on it. As I expected that float64array would be at least as fast as float32

AlteredQualia

I'm getting much lower performance with 64 bit floats - 35 fps vs 60 fps on webgl_performance stress test (using @gero3's commit).

kovleouf

I tried with @gero3's commit and it fixes my precision issues.

AlteredQualia

Yay! So I guess this should be toggleable by some flag (with default set to use Float32Array).

@mrdoob Maybe something like this?

THREE.FloatArrayType = Float32Array;
THREE.FloatArrayType = Float64Array;

Not sure though how to override this nicely from the application layer, there are objects which are created simply by including the lib, so these must be somehow aware of the override :/.

It could be something like this, but it's quite ugly:

<script>
var THREE =  { FloatArrayType: Float64Array };
</script>

<script src="../build/Three.js"></script>

And then inside Three.js:

if ( THREE.FloatArrayType === undefined ) {

    THREE.FloatArrayType = Float32Array;

}

And in Matrix4:

this.elements = new THREE.FloatArrayType( 16 );
Mr.doob
Owner

Maybe something like THREE.Matrix4.set64bit()? which would set a static flag that every matrix would check at instantiation time. It's basically Matrix4, right?

AlteredQualia

Matrix4 and Matrix3.

But trouble are static matrices that are created at lib loading time - if we set it like this, they would have been already created in a different way and thus incompatible :S.

Now we could reset these in THREE.Matrix4.set64bit() but this would be also bad design, fragile as we would need to collect all such static matrices there.

Mr.doob
Owner

Meh...

@kovleouf would anything change if you divided all your values by 1000?

AlteredQualia

@mrdoob Another option could be doing this at the build time (we would build the lib with either 32 or 64 bit typedef file included).

Then we would have a special version of the lib Three64.js, to be used if application needs higher precision (somehow similar to how binary applications have 32 and 64 bit versions).

@kovleouf Sanity check - do you use proper mathematical constants everywhere?

For example I remember having precision artefacts when I used numbers like 3.14 instead of Math.PI. This was ok when my scenes were small, but on large scenes imperfections were popping up (especially treacherous were rotations of larger planes, tiny angular difference can make a huge displacement).

Mr.doob
Owner

So seems like the only option is having it run slower. I wonder if that's ok with @kovleouf or whether there's something that he can do on his app code instead ;)

kovleouf

@mrdoob : i can't divide everything by 1000 because i'm working on an earth map using real lon / lat coordinate system so it would be a pain to convert everything.

@alteredq : i'm using Math.XXX constants, the precision error is due to the huge size of my world.

I will investigate the performances with r48, r49 32bits and r49 with the quick 64bits hack today

kovleouf

I'm running with 6-10 ms / frame on r48 and r49 and 10-15 ms / frame on r49 with float64Array.

I think i'll keep my project under r48 for now

Mr.doob
Owner

What browser/system is that on?

kovleouf

Window XP SP3
Intel core 2 Duo 2.4Ghz
3.50 Go RAM
GeForce GTX 260 Ultra
Chrome 18.0.

I tried with the 2nd version of @gero3 (Pull Request #1903) and i'm running with 8-12ms / frame. (i can't give a real FPS because i refresh the frame only when something changes)

Mr.doob
Owner

So you get 6-10ms with Number, 10-15 with Float32Array and 8-12 with Float64Array?

kovleouf

no :
6-10ms with Number
6-10ms with Float32Array but precision issue
8-12ms with Float64Array and conversion code to prevent precision issue

Mr.doob mrdoob closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.