View Full Version : random number generation with cg
k.arts 07012005, 07:55 AM Hello there.
I need a random number generation in cg. I know, theres a noise function which gives me a value between 0 and 1 for a given input. Problem is, that this function produces always the same output for a given input... Does anyone know a solution like the srand() and rand() thing in c? Or do I have to supply a texture with random values which would than be read by the shader? If this is the only way, does anyone have an idea, how to do this fast(filling such a texture with random values)
Thanks a lot
k.arts


The answer to that question is very cool.
rand() make a random number between 0 and 1, such as: 0.456, 0.361... From that number we need ANY number, how do we do that?? Very simple. Look at this numbers:
NOTE: % means the reminder of the division.
0 % 3 = 0 (The reminder of the division 0 / 3 = 0)
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
7 % 3 = 1
8 % 3 = 2
9 % 3 = 0
The reminders of a division by 3 are always 0, 1 or 2... let's test another number...
0 % 10 = 0
1 % 10 = 1
2 % 10 = 2
3 % 10 = 3
4 % 10 = 4
5 % 10 = 5
6 % 10 = 6
7 % 10 = 7
8 % 10 = 8
9 % 10 = 9
10 % 10 = 0
11 % 10 = 1
12 % 10 = 2
13 % 10 = 3
14 % 10 = 4
15 % 10 = 5
16 % 10 = 6
17 % 10 = 7
18 % 10 = 8
19 % 10 = 9
The reminders are always between 0 and 9... Coincidence?? not... If you want to get a number between 0 and 5 (for example) you can get the reminder of the division between a random number and 6. Do you know what I mean?
And now, if you want a random number between 5 and 10??? what can we do?, very simple...
(rand() % 6) + 5: With out adding 5, we would get 0, 1, 2, 3, 4, 5 or 6. If we add 5... we get 0+5, 1+5, 2+5... Ok??
So with that we could make a funcion (such as the one in PHP):
1 int ourRandNumber(int from, int to)
2 {
3 int total = (to  from);
4 total++;
5
6 srand((unsigned)time(NULL) + rand() % rand());
7 int random = (rand() % total) + from;
8
9 return random;
10 }
NOTE: The line 6 is for making a more ramdomized number, and you've got to include the <time.h>
I hope I've explained well... excuse me if my english is a little bad, I'm spanish and I'm 14...
Bye ;)
DaKrunch
07122005, 07:29 AM
N4x0: sorry guy. The answer is very well explained but it is not what he wanted, i believe.
not that you wrote anything wrong by itself but your algorithm presumes the builtin random generator returns any number, presumably big, and evenly spaced (therefore integers or fixedpoint). the % operator needs such numbers.
K.Arts told it returns a float between 0 and 1 instead. Shaders most often work with floating point values.
k.arts: why would a shader want a random  i mean not repeatable  number? Don't you want to be the same from frame to frame?
anyway if you want a sequence of random numbers (e.g. for a noise) you might just take any varying input on the surface. U, V are an example. X,Y,Z are another.
also if you want a random sequence with a function that takes one input, so that it looks like rand and srand consider this
float seed = ...
float sequence[n];
(being myrand the function you say you have in cg)
sequence[0] = myrand(seed);
for (i = 1 to n)
sequence [i] = myrand(sequence[i1]);
is theoretically equivalent to C code:
srand(seed);
for (i = 0 to n)
sequence[i] = rand();
DaKrunch
07122005, 07:33 AM
also you might consider creating your own randomization routine. They are just a combination of sums and multiplications with big prime numbers  depending on the bitdepth of your data structures. 3 or 4 iterations are usually enough to achieve a visually random distribution
shadowMaster
07122005, 11:40 PM
I need a random number generation in cg. I know, theres a noise function which gives me a value between 0 and 1 for a given input. Problem is, that this function produces always the same output for a given input...
noise() can easily emulate a random number generator. (This is very much what Da Krunch is also saying) If you want a stream of random numbers, just give a counter as input to noise(). I don't know cg, or what kind of noise it is, but if it's Perlin noise, then you also want to do two things: 1 add 0.5 to your integer input value (Perlin always returns 0 at integer values), and 2 spread the output value (the result of Perlin noise(Z+0.5) is not uniform and also generally doesn't fully reach the range [1,1]), so multiply by a large constant number and fmod with 1.0.
I actually prefer this kind of RNG (often called 'white noise') because there are many situations where having a repeatable random number generator is really really really useful. You don't have to have an srand() call, since you have full control over how you stream your random numbers. You can restart a stream just by resetting your counter, you can even restart in the middle of a stream, or run it backwards, and you can support multiple simultaneous streams trivially and in a threadsafe way...I *love* white noise.
CGTalk Moderation
07122005, 11:40 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.