Jump to content

  • Log In with Google      Sign In   
  • Create Account


Computing big numbers in shaders of WebGL/OpenGL


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 lallish   Members   -  Reputation: 154

Like
0Likes
Like

Posted 10 December 2013 - 03:15 PM

Hello.

 

I'm in need of computing floats larger than 32-bit in my vertex-shaders.

float phi = index* inc;                     // big number, "5476389.695241543"-biggish
float cosPhi = cos(phi);                

phi is unnecessary big, contains a lot of trigonometric loops and the important decimal precision are removed as it's a 32-bit float. Is there a way to remove all the unnecessary 2*PI loops on phi before it get saved to the float?



Sponsor:

#2 fastcall22   Crossbones+   -  Reputation: 3527

Like
0Likes
Like

Posted 10 December 2013 - 03:38 PM

So, mod then? I haven't worked with shaders, but I believe you're looking for:
float phi = mod( index * inc, 2*pi );
float cosPhi = cos(phi);

WW91J3ZlIGdvdCBhIHNlY3JldCBib251cyBwb2ludCE=


#3 Álvaro   Crossbones+   -  Reputation: 11705

Like
1Likes
Like

Posted 11 December 2013 - 01:06 AM

How about this?
float index_mod_2pi = mod(index, 2*pi);
float inc_mod_2pi = mod(inc, 2*pi); // EDIT: Fixed typo (thanks Vilem Otte)
float cosPhi = cos(index_mod_2pi * inc_mod_2pi);
Or you may have to use `fmod' instead (I think GLSL has `mod' and HLSL has `fmod', but I am not sure, and either one would work in this case).

Edited by Álvaro, 11 December 2013 - 03:23 AM.


#4 Vilem Otte   Crossbones+   -  Reputation: 1344

Like
0Likes
Like

Posted 11 December 2013 - 02:40 AM

Alvaro's solution is good, as it most likely will result in better-precise result (and I'd say enough precise one). I just confirm that yes, GLSL has mod and GLSL fmod. Note that you have a bug in the code you wrote, the second line should actually have 'inc' as 1st argument into mod on 2nd line.

 

Now to the thing I wanted to write ... in case you would need even more precision, you *can* use double-precision floating point numbers on gpu, in OpenGL it's through extension GL_ARB_gpu_shader_fp64, in HLSL I'm sure that in D3D 11.1 (I also think that 11.0 supports them but I'm not sure -> if someone checking this works with D3D, please confirm), it is possible to use them.

 

In OpenGL you can use glUniform*d, glUniform*dv, glUniformMatrix*dv and also when GL_EXT_direct_state_access is supported, then glProgramUniform*d, glProgramUniform*dv, glProgramUniformMatrix*dv. Your variables are then declared as double/dvec/dmat in shader.


Edited by Vilem Otte, 11 December 2013 - 02:45 AM.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com


#5 lallish   Members   -  Reputation: 154

Like
0Likes
Like

Posted 11 December 2013 - 01:16 PM

Thanks for replies guys, appreciate it. But...

How about this?

float index_mod_2pi = mod(index, 2*pi);
float inc_mod_2pi = mod(inc, 2*pi); // EDIT: Fixed typo (thanks Vilem Otte)
float cosPhi = cos(index_mod_2pi * inc_mod_2pi);
Or you may have to use `fmod' instead (I think GLSL has `mod' and HLSL has `fmod', but I am not sure, and either one would work in this case).

 

(A * B) mod C != (A mod C) * (B mod C)....it is = ( (A mod C) * (B mod C) ) mod C

 

But how is this compiled when you multiply two floats like this and it exceeds 32-bit in the multiplication, can they go over that precision until you save it in a float? I still have precision errors



#6 Álvaro   Crossbones+   -  Reputation: 11705

Like
0Likes
Like

Posted 11 December 2013 - 03:57 PM

Thanks for replies guys, appreciate it. But...

How about this?

float index_mod_2pi = mod(index, 2*pi);
float inc_mod_2pi = mod(inc, 2*pi); // EDIT: Fixed typo (thanks Vilem Otte)
float cosPhi = cos(index_mod_2pi * inc_mod_2pi);
Or you may have to use `fmod' instead (I think GLSL has `mod' and HLSL has `fmod', but I am not sure, and either one would work in this case).

(A * B) mod C != (A mod C) * (B mod C)....it is = ( (A mod C) * (B mod C) ) mod C


The last "mod C" is provided by the periodicity of the cosine function, so you don't really need it.
 

But how is this compiled when you multiply two floats like this and it exceeds 32-bit in the multiplication, can they go over that precision until you save it in a float? I still have precision errors

What do you mean by "it exceeds 32-bit in the multiplication"? What bits are you talking about? Either you don't understand what floats are, or I don't understand what you are saying.

#7 lallish   Members   -  Reputation: 154

Like
0Likes
Like

Posted 12 December 2013 - 05:45 AM

The last "mod C" is provided by the periodicity of the cosine function, so you don't really need it.

 

Ah cool.

 

What do you mean by "it exceeds 32-bit in the multiplication"? What bits are you talking about? Either you don't understand what floats are, or I don't understand what you are saying. 

 

Yea I worded it a bit badly. But what I meant was when we do this: 

float cosPhi = cos(index_mod_2pi * inc_mod_2pi);

the inner multiplication:

index_mod_2pi * inc_mod_2pi

doesn't this get saved to a 32-bit memory address stored temporarily until we do cos(this_stored_address) hence losing precision, or am I completely wrong? Because I seem to get much higher precision if I calculate index_mod_2pi * inc_mod_2pi on the CPU with 64-bit addresses and then send it in as uniform or attribute.


Edited by lallish, 12 December 2013 - 06:02 AM.


#8 Álvaro   Crossbones+   -  Reputation: 11705

Like
0Likes
Like

Posted 12 December 2013 - 07:11 AM

Your terminology is imprecise. 32-bit addresses or 64-bit addresses have nothing to do with this discussion. There is a 32-bit floating-point type (a.k.a. "single-precision", or "float") and a 64-bit floating-point type (a.k.a. "double precision", or "double"). The original question used single-precision numbers, and although it is possible to use double-precision numbers in shaders in some circumstances, not every card supports it, and the ones that do have many fewer cores capable of double-precision computation. So we are basically constrained to single-precision computations.

[EDIT: To learn about floating-point types, Google for "IEEE 754 introduction" or "what every computer scientist should know about floating-point arithmetic".]

Within single-precision computations, I think what I posted is about the best you can do.

Edited by Álvaro, 12 December 2013 - 07:13 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS