Advertisement Jump to content
Sign in to follow this  
lallish

OpenGL Computing big numbers in shaders of WebGL/OpenGL

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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

Share this post


Link to post
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 this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!