• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lallish

Javascript's “Math.sin/Math.cos” and WebGL's “sin/cos” give different results

12 posts in this topic

I'm trying to generate fibonacci distributed points on a sphere. However when I try to do so in the shader on the GPU, the calculation of sin/cos becomes very different than if I would have calculated Math.sin/Math.cos on the CPU. Here is part of the vertex shader of the fibonacci function:
 
    
attribute float index;          //array with numbers between [1, 2500000]


       float inc = 3.141592653589793238462643383279 * (3.0 - sqrt(5.0));
       float off = 2.0 / 2500000;
       float yy = index * off - 1.0 + (off / 2.0);
       float rr = sqrt(1.0 - yy * yy);
       float phi = index* inc;                     // big number, "5476389.695241543"-biggish
       vec3 fibPoint = vec3(cos(phi) * rr, yy, sin(phi) * rr);  // calculates sin/cos wrong
 
This part gives the wrong fibPoint vectors of locations that looks like this: http://i.imgur.com/Z1crisy.png
 
And when I calculate the Math.sin(phi) and Math.cos(phi) of the fibPoint vector in javascript, and throw these values in as attributes into the shader instead, so the code looks like:
 
   
 /* short version of code from javascript */
    var y = index * off - 1 + (off / 2.0);
    var r = Math.sqrt(1 - y * y);
    var phi = index * inc;
    var cosphi = Math.cos(phi);
    var sinphi = Math.sin(phi);
      ....
      ..


    /* throw cosphi/sinphi into the shader as attributes along with the index */
    
    
    /* vertex shader */
    attribute float index;
    attribute float sinphi;
    attribute float cosphi;


       float inc = 3.141592653589793238462643383279 * (3.0 - sqrt(5.0));
       float off = 2.0 / 2500000;
       float yy = index * off - 1.0 + (off / 2.0);
       float rr = sqrt(1.0 - yy * yy);
       //float phi = index* inc;
       vec3 fibPoint = vec3(cosphi * rr, yy, sinphi * rr);
 
 
This gives the correct fibPoint vectors. Now the locations looks like this: http://i.imgur.com/DeRoXkL.png
 
So my question is, why doesn't WebGL's sin/cos give same or similar result as javascript's Math.sin/cos? As far as I know, both input is radians, and both output [-1, 1]. May it be because "phi" are too large numbers so some part get truncated in the cos/sin?
 
Thanks for reading.
 
0

Share this post


Link to post
Share on other sites

Maybe I am completely off here, but if your desire is for the cubes to be distributed across the surface of a sphere, why not make the inputs to sin and cos lie between -pi and pi? This would make the initial positions lie on a unit sphere and then you can scale them by the radius of the large sphere to get their final positions.

1

Share this post


Link to post
Share on other sites

Thanks for that information Cornstalks. Do you suggest calculating the fibPoint on the CPU instead and throw the vec3 in as an attribute? Because I'll be dealing with much larger numbers later, index might go as high as 400 000 000

 

Maybe I am completely off here, but if your desire is for the cubes to be distributed across the surface of a sphere, why not make the inputs to sin and cos lie between -pi and pi? This would make the initial positions lie on a unit sphere and then you can scale them by the radius of the large sphere to get their final positions.

 

 

Yes, I could do that, with something like: 

float tphi = phi - twoPI*ceil(phi/twoPI - 1.0);

But I would still need the precision of phi to do that, and "yy" and "off" too if I expand my index in the future.

Edited by lallish
0

Share this post


Link to post
Share on other sites

Computing that number in Javascript on the CPU solves the problem only partially. At some point you may have problems using doubles too. Big numbers and trigonometric functions do not work really well together... Why are you using such formula to generate the points?

1

Share this post


Link to post
Share on other sites

Thanks for that information Cornstalks. Do you suggest calculating the fibPoint on the CPU instead and throw the vec3 in as an attribute? Because I'll be dealing with much larger numbers later, index might go as high as 400 000 000

If the points don't move around and are static, that might make the most sense to do. Even if you simplify the formula to be ?j = arccos(1 - (2j + 1) / N), ?j = 2j??-1, 0 <= j < N, you run into precision errors as j grows > 999,999 using 32-bit floats.

 

 

Computing that number in Javascript on the CPU solves the problem only partially. At some point you may have problems using doubles too. Big numbers and trigonometric functions do not work really well together... Why are you using such formula to generate the points?

It's a specific formula for generating a perfect distribution of points over a sphere.

1

Share this post


Link to post
Share on other sites

Computing that number in Javascript on the CPU solves the problem only partially. At some point you may have problems using doubles too. Big numbers and trigonometric functions do not work really well together... Why are you using such formula to generate the points?

I want to distribute points equally over a sphere and I don't know another way of doing so, do you know of a better formula?

 

If the points don't move around and are static, that might make the most sense to do. Even if you simplify the formula to be ?j = arccos(1 - (2j + 1) / N), ?j = 2j??-1, 0 <= j < N, you run into precision errors as j grows > 999,999 using 32-bit floats.

 

 

They are static yep. What I will try now then is to use Web Workers to calculate the points to off load the main thread in javascript, only thing I'm afraid of is how many attributes I can update at the same time without any major performance hit, as it is three floats now instead of just a single index float.

Edited by lallish
0

Share this post


Link to post
Share on other sites

They are static yep. What I will try now then is to use Web Workers to calculate the points to off load the main thread in javascript, only thing I'm afraid of is how many attributes I can update at the same time without any major performance hit, as it is three floats now instead of just a single index float.

You could do it with 2 floats and 1 uniform: the two floats are phi (in range [0, pi]) and theta (in range [0, 2pi]), and the uniform is the sphere's radius.

 

If that turns out to be too many objects you may need to do some space partitioning.

1

Share this post


Link to post
Share on other sites

If I understand properly the problem is that as "index" grows arbitrarily large, which means "index * inc" (where "inc" corresponds to some rotation in radians) loses all fractional precision, where it matters. The expected output is an aperiodic list of angles 0, inc, 2inc, 3inc, etc.. wrapping around the unit circle.

 

To that end, why not simply keep a running sum of the angle (phi) by adding "inc" at each iteration, and subtract 2 * pi every time phi exceeds 2 * pi (do that on the CPU). That will solve the problem nicely.

 

Or something like that. Maybe I misunderstood.

0

Share this post


Link to post
Share on other sites

You could do it with 2 floats and 1 uniform: the two floats are phi (in range [0, pi]) and theta (in range [0, 2pi]), and the uniform is the sphere's radius.

 

If that turns out to be too many objects you may need to do some space partitioning.

 

Yep, that's correct. Thanks!

 

If I understand properly the problem is that as "index" grows arbitrarily large, which means "index * inc" (where "inc" corresponds to some rotation in radians) loses all fractional precision, where it matters. The expected output is an aperiodic list of angles 0, inc, 2inc, 3inc, etc.. wrapping around the unit circle.

 

To that end, why not simply keep a running sum of the angle (phi) by adding "inc" at each iteration, and subtract 2 * pi every time phi exceeds 2 * pi (do that on the CPU). That will solve the problem nicely.

 

Or something like that. Maybe I misunderstood.

 

It would work, except I don't do it iterative, I fetch precomputed indices from surrounding and only generate the needed points.

Edited by lallish
0

Share this post


Link to post
Share on other sites
I didn't know this algorithm to generate uniform points on a sphere. smile.png That's interesting.. How do you assign indices to regions? Wouldn't be easier to just assign the precomputed points instead of the indices?

If all you need is generate a uniform set of points on some sub-region of the sphere, a set of spherical triangles for example, you can also use some kind of uniform sampling strategy on spherical triangles. I know one algorithm which can be found in the chapter "Stratified Sampling of 2-Manifolds" by James Arvo in the "State of the Art in Monte Carlo Ray Tracing for Realistic Image Synthesis" Siggraph 2001 course. This is quite expensive however. There may be faster methods which I don't know.
0

Share this post


Link to post
Share on other sites

I didn't know this algorithm to generate uniform points on a sphere. smile.png That's interesting.. How do you assign indices to regions? Wouldn't be easier to just assign the precomputed points instead of the indices?

If all you need is generate a uniform set of points on some sub-region of the sphere, a set of spherical triangles for example, you can also use some kind of uniform sampling strategy on spherical triangles. I know one algorithm which can be found in the chapter "Stratified Sampling of 2-Manifolds" by James Arvo in the "State of the Art in Monte Carlo Ray Tracing for Realistic Image Synthesis" Siggraph 2001 course. This is quite expensive however. There may be faster methods which I don't know.

I have an Icosahedron sphere, which is divided into almost equally big triangles, or hexagons with an occasional pentagon, so they create a tile system for you if you're inside the sphere. And each triangle have assigned indices to them. 

 

And why I've precomputed indices and not the actual points is a good question! It's a matter of reducing the size of the files, especially if it's a file that a client will download from your webserver, reducing the file transfer by half might be a better choice than the small performance hit your client will get from computing the points him/herself. I'm still experimenting, Just now, the indices in the interval [0, 2500000] so far take 18 mb. But, as the indices grow higher, the points will remain with a consistent precision, and size. So in the future when I know more about Javascript compression, I'll probably consider precomputing the points instead.

0

Share this post


Link to post
Share on other sites
I'm not an expert on JavaScript but if your points are static, then I think it is probably better to create all the point once on the CPU side and then load them in some static buffer. Using this solution you can later decide to directly send the points without changing the rendering code and you can use doubles for the increased precision they provide.
Are you transmitting all the data at once or on demand? If you only need a small subset of the indices you may save some time requesting the indices only when needed. Have you tried compressing your file?
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0