• Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at \$59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.

Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!

# 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.

7 replies to this topic

### #1lallish  Members   -  Reputation: 191

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?

### #2fastcall22  Crossbones+   -  Reputation: 4476

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);


c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

### #3Álvaro  Crossbones+   -  Reputation: 13933

Like
1Likes
Like

Posted 11 December 2013 - 01:06 AM

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.

### #4Vilem Otte  Crossbones+   -  Reputation: 1568

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

### #5lallish  Members   -  Reputation: 191

Like
0Likes
Like

Posted 11 December 2013 - 01:16 PM

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

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: 13933

Like
0Likes
Like

Posted 11 December 2013 - 03:57 PM

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

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.

### #7lallish  Members   -  Reputation: 191

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: 13933

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