# OpenGL Computing big numbers in shaders of WebGL/OpenGL

This topic is 2142 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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?

##### Share on other sites
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);


##### Share on other sites
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

##### Share on other sites

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

##### Share on other sites

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

##### Share on other sites

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.

##### Share on other sites
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

##### Share on other sites
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

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 16
• 9
• 15
• 9
• 11