51,43 → 51,13 |
------------------- |
|
Filter Foundry's implementation of rst(i) (undocumented function that sets the seed for the PRG) |
differs from the implementation of Filter Factory. |
and rnd(a,b) (generate random number between a and b, inclusively) |
differs from the implementation of Filter Factory in many ways. |
|
1. In Filter Foundry, the function rnd(a,b) retrieves a random number at realtime; therefore, if the |
seed is changed via rst(i), there is an immediate effect on the next call of the rnd(a,b) function. |
For example, following filter would generate an one-colored picture without any randomness: |
R=rst(123), rnd(0,255) |
G=rnd(0,255) |
B=rnd(0,255) |
1. In Filter Foundry, the random seed is automatically initialized with seed 691204. |
In Filter Factory, the random seed is automatically initialized with seed 0. |
|
In Filter Factory, the rnd(a,b) function is more complex. |
(The analysis of Filter Factory's rnd and rst function is not yet completed, so |
following notes might not be 100% accurate.) |
It seems like there is a buffer with 56 random integers that will be refilled regularly. |
The rst(i) function seems to change the seed for the next batch of random numbers, |
so there is not immediate effect on the rnd() calls. |
|
2. Furthermore, it seems like in Filter Factory, if rst(i) is called multiple times |
with the same argument, there will be no effect. |
So, while following filter would generate random vertical bars in Filter Foundry, |
it would generate a picture with random pixels in Filter Factory: |
R=(x==0) ? rst(123) : 0, rnd(0,255) |
G=0 |
B=0 |
|
In Filter Foundry, every call of rst(i) will perform an update of the seed. |
So, if you like to have a random-pixel picture with a specific seed, |
you must make sure that rst(i) will only be called once. |
You would need to write your filter like this |
R=(x==0 && y==0) ? rst(123) : 0, rnd(0,255) |
G=0 |
B=0 |
if you want generate a similar result as Filter Factory outputs with the filter |
R=rst(123), rnd(0,255) |
G=0 |
B=0 |
|
3. In Filter Foundry, the argument i of the function rst(i) is limited to the |
2. In Filter Foundry, the argument i of the function rst(i) is limited to the |
type "unsigned int" (argument of the function srand() in the C StdLib), |
so the allowed range is 0..4294967295. |
|
95,10 → 65,79 |
If the argument is not within this range, the operation "and 0x7FFF" will be applied to it |
to extract the low 15 bits. |
|
3. In Filter Foundry, the function rnd(a,b) retrieves a random number at realtime; therefore, if the |
seed is changed via rst(i), there is an immediate effect on the next call of the rnd(a,b) function. |
For example, following filter would generate an one-colored picture without any randomness: |
R: rst(123), rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255) |
If you want to generate a random pixel image with a non-default seed, you need to make sure |
that rst(i) is called only once at the beginning (channel 0, coordinate 0|0): |
R: (x==0 && y==0) ? rst(123) : 0, rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255) |
|
In Filter Factory, the rnd(a,b) function is more complex. |
As soon as the function rnd(a,b) is used once, rst(i) will not have any effect. |
So, if you want to use rst(i), you must make sure to call it before using rnd(a,b). |
Following filter will generate a random pixel picture: |
R: rst(123), rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255) |
Following filter would generate a different random pixel picture: |
R: rst(456), rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255) |
Following filter would generate the same random pixel picture: |
R: rst(456), rnd(0,255)+rst(123) <-- note that rst() always returns 0, so the '+' operator is OK |
G: rnd(0,255) |
B: rnd(0,255)+rst(456) <-- the last rst(456) call is to mitigate a bug; see below. |
|
4. In Filter Factory, due to a bug, the random state is not reset to its initial state (0) before the filter is applied: |
The preview image processing will modify the random state, and once the filter is actually applied (pressing "OK"), |
the random state that was set in the preview picture, will be used. |
Example: |
R: rnd(0,255), rst(123) <-- note that the rst(123) is ignored because rnd() was already called. |
G: rnd(0,255) |
B: rnd(0,255) |
This filter will produce a random pixel picture with the initial default random seed 0, |
but only for the first calculation (i.e. in the preview picture processing, or in a standalone filter without dialog). |
Any further calculation will result in a random pixel picture with random seed 123, |
since the random seed 123 will be taken from the previous run. |
|
Furthermore, the random state can't be changed again, not even at the beginning of the red channel before any rnd() call. |
Example: |
R: rst(333), rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255)+rst(555) |
This filter will produce a picture with random seed 333 on the first calculation, |
and at every further calculation, a random picture with seed 555. |
Another example: |
R: rst(ctl(0)), rnd(0,255) |
G: rnd(0,255) |
B: rnd(0,255)+rst(555) |
In this filter, the slider value is ignored and the resulting picture will always be the same. |
|
|
Evaluation of conditional branches |
---------------------------------- |
|
Filter Foundry: |
Only the branches which will be chosen due to the conditional expression will be evaluated. |
This means that following filter would generate a black canvas: (Testcase conditional_eval_1.afs) |
R: 1==0 ? put(255,0) : 0 |
G: get(0) |
B: 0 |
In boolean expressions, the evaluation will be aborted if the result is already determined. |
So, this will also generate a black canvas: (Testcase conditional_eval_2.afs) |
R: 1==0 && put(255,0) ? 0: 0 |
G: get(0) |
B: 0 |
This will also generate a black canvas: (Testcase conditional_eval_3.afs) |
R: 1==1 || put(255,0) ? 0 : 0 |
G: get(0) |
B: 0 |
|
Filter Factory: |
Each branch inside a if-then-else expression will be evaluated. |
This means that following filter would generate a green canvas: (Testcase conditional_eval_1.afs) |
105,25 → 144,12 |
R : 1==0 ? put(255,0) : 0 |
G : get(0) |
B : 0 |
A : 255 |
Also, all arguments of an boolean expression will be fully evaluated. |
So, this will also generate a green canvas: (Testcase conditional_eval_2.afs) |
R : 1==0 && put(255,0) ? 0: 0 |
G : get(0) |
B : 0 |
A : 255 |
|
|
Filter Foundry: |
Only the branches which will be chosen due to the conditional expression will be evaluated. |
This means that following filter would generate a black canvas: (Testcase conditional_eval_1.afs) |
R : 1==0 ? put(255,0) : 0 |
This will also generate a green canvas: (Testcase conditional_eval_3.afs) |
R: 1==1 || put(255,0) ? 0 : 0 |
G : get(0) |
B : 0 |
A : 255 |
In boolean expressions, the evaluation will be aborted if the result is already determined. |
So, this will also generate a black canvas: (Testcase conditional_eval_2.afs) |
R : 1==0 && put(255,0) ? 0: 0 |
G : get(0) |
B : 0 |
A : 255 |