Is exp(x) where x is negative infinity guaranteed to evaluate to zero in GLSL?
If you obtain negative infinity through that -1/0.f, you can try in your fragment shader to set your output color to vec4(exp(-1/0.f),exp(-1/0.f),exp(-1/0.f), 1.f) and see the color.
I've just tried and the output is black(so equal to 0) in OGL 4.5. And by the limit of the exponential function, lim(-inf) = 0, so it must be a zero garanteed.
Hope this helped ^^.
Related
Recently I found this interesting thing in webkit sources, related to color conversions (hsl to rgb):
http://osxr.org/android/source/external/webkit/Source/WebCore/platform/graphics/Color.cpp#0111
const double scaleFactor = nextafter(256.0, 0.0); // it's here something like 255.99999999999997
// .. some code skipped
return makeRGBA(static_cast<int>(calcSomethingFrom0To1(blablabla) * scaleFactor),
Same I found here: http://www.filewatcher.com/p/kdegraphics-4.6.0.tar.bz2.5101406/kdegraphics-4.6.0/kolourpaint/imagelib/effects/kpEffectHSV.cpp.html
(int)(value * 255.999999)
Is it correct to use such technique at all? Why dont' use something straight like round(blabla * 255)?
Is it features of C/C++? As I see strictly speaking is will return not always correct results, in 27 cases of 100. See spreadsheet at https://docs.google.com/spreadsheets/d/1AbGnRgSp_5FCKAeNrELPJ5j9zON9HLiHoHC870PwdMc/edit?usp=sharing
Somebody pls explain — I think it should be something basic.
Normally we want to map a real value x in the (closed) interval [0,1] to an integer value j in the range [0 ...255].
And we want to do it in a "fair" way, so that, if the reals are uniformly distributed in the range, the discrete values will be approximately equiprobable: each of the 256 discrete values should get "the same share" (1/256) from the [0,1] interval. That is, we want a mapping like this:
[0 , 1/256) -> 0
[1/256, 2/256) -> 1
...
[254/256, 255/256) -> 254
[255/256, 1] -> 255
We are not much concerned about the transition points [*], but we do want to cover the full the range [0,1]. How to accomplish that?
If we simply do j = (int)(x *255): the value 255 would almost never appear (only when x=1); and the rest of the values 0...254 would each get a share of 1/255 of the interval. This would be unfair, regardless of the rounding behaviour at the limit points.
If we instead do j = (int)(x * 256): this partition would be fair, except for a sngle problem: we would get the value 256 (out of range!) when x=1 [**]
That's why j = (int)(x * 255.9999...) (where 255.9999... is actually the largest double less than 256) will do.
An alternative implementation (also reasonable, almost equivalent) would be
j = (int)(x * 256);
if(j == 256) j = 255;
// j = x == 1.0 ? 255 : (int)(x * 256); // alternative
but this would be more clumsy and probably less efficient.
round() does not help here. For example, j = (int)round(x * 255) would give a 1/255 share to the integers j=1...254 and half that value to the extreme points j=0, j=255.
[*] I mean: we are not extremely interested in what happens in the 'small' neighbourhood of, say, 3/256: rounding might give 2 or 3, it doesn't matter. But we are interested in the extrema: we want to get 0 and 255, for x=0 and x=1respectively.
[**] The IEEE floating point standard guarantees that there's no rounding ambiguity here: integers admit an exact floating point representation, the product will be exact, and the casting will give always 256. Further, we are guaranteed that 1.0 * z = z.
In general, I'd say (int)(blabla * 255.99999999999997) is more correct than using round().
Why?
Because with round(), 0 and 255 only have "half" the range that 1-254 do. If you round(), then 0-0.00196078431 get mapped to 0, while 0.00196078431-0.00588235293 get mapped to 1. This means that 1 has 200% more probability of occurring than 0, which is, strictly speaking, an unfair bias.
If, isntead, one multiplies by 255.99999999999997 and then floors (which is what casting to an integer does, since it truncates), then each integer from 0 to 255 are equally likely.
Your spreadsheet might show this better if it counted in fractional percentages (i.e. if it counted by 0.01% instead of 1% each time). I've made a simple spreadsheet to show this. If you look at that spreadsheet, you'll see that 0 is unfairly biased against when round()ing, but with the other method things are fair and equal.
Casting to int has the same effect as the floor function (i.e. it truncates). When you call round it, well, rounds to the nearest integer.
They do different things, so choose the one you need.
I'm trying to get the value from the thumbstick with XInput, but the values are weird and I don't know how to handle them correctly.
How do I calculate so that I can read the values between -1 (thumbstick to the left/up) +1 (thumbstick to the right/down)
Similiar to XNA's Gamepad.GetState().ThumbSticks.Left.X ( -1 = to the left, +1 = to the right ).
Any ideas?
According to the documentation, _XINPUT_GAMEPAD.sThumbLX is a SHORT whose value lies between -32768 and 32767. If you want to convert that to a range of [-1, 1), divide the value by 32768.0.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Floating point comparison
Well this is a strange one. Ordinarily the following if( 4.0 == 4.0 ){return true} will always return true. In a simple little opengl 3d 'shooter' program I have, when I am trying to add 'jumping' effects, this is not the case.
The idea is fairly simple, I have a terrain of triangle strips, as the 'character' moves/walks you move along a 2d array of heights, hence you walk up and down the various elevations in the hills/troughs.
Outside of the drawScene() function (or if you know opengl, the glutDisplayFunc()), I have an update() function which raises the character up and down as he 'jumps', this is called in drawScene(). In words, as high level as I can explain it, the jumping algorithm is below:
parameters:
double currentJumpingHeight
double maximumJumpingHeight = 4.0
double ypos;
const double jumpingIncrement = 0.1; //THE PROBLEM!!!! HAS TO BE A MULTIPLE OF 0.5!!
bool isJumping = false;
bool ascending = true;
the algorithm:
(when space is pressed) isJumping = true.
if ascending = true and isJumping = true,
currentJumpHeight += jumpingIncrement (and the same for ypos)
if currentJumpingHeight == maximumJumpingHeight, //THE PROBLEM
ascending = false
(we decrement currentJumpingHeight and start to fall until we hit the ground.)
Its very simple, BUT IT ONLY WORKS WHEN jumpingIncrement IS A MULTIPLE of 0.5!!
If jumpingIncrement is, say, 0.1, then currentJumpingHeight will never equal maximumJumpingHeight. The character takes off like a rocket and never returns to the ground. Even when the two variables are printed to the standard output and are the same, the condition is never true. This is the problem I would like to solve, it is absurd.
I don't want any feedback on the jumping algorithm - just the above paragraph please.
please help.
It's just a typical floating point precision problem. In particular 0.1 cannot be represented exactly using binary floating points. Numbers like 0.5 and 0.25 on the other hand can be represented exactly, and thus will probably work. I believe the compiler is still free to make it not work, even in that case.
In your case a solution is using >=:
if ascending && (currentJumpingHeight >= maximumJumpingHeight)
ascending = false
currentJumpingHeight = maximumJumpingHeight
You could also use epsilon comparisons, but I avoid them where possible. In your case a simple >= seems cleaner than epsilon equality.
As people said, it's a typical floating precision point problem. Look at this
Basically, in the same way you can't code with a finite number of digits 1/3 in base 10
1/3 = 0.3333333333.....
You can't do 1/10 in base 2.
It will be
0.1 = 0x0.0001100110011001100110011001100110011001100110011...
You should never compare floats but check that there difference is smaller than a value, ex
if (fabs(a-b) < 1e-6)
instead of
if(a==b)
Of course in your case, just use '>='.
It work with your 0.5 increment, because 0.5 is 1/2 or 0.1 in binary, so it's coded properly .
That will work for any power of 2 so 0.5 or 0.125, but never with 0.1.
Rephrasing question :
The following code (Not C++ - written in an in-house scripting language)
if(A*B != 0.0)
{
D = (C/(A*B))*100.0;
}
else
{
D = 0.0;
}
yields a value of
90989373681853939930449659398190196007605312719045829137102976436641398782862768335320454041881784565022989668056715169480294533394160442876108458546952155914634268552157701346144299391656459840294022732906509880379702822420494744472135997630178480287638496793549447363202959411986592330337536848282003701760.000000
for D. We are 100% sure that A != 0.0. And we are almost 100% sure that B == 0.0. We never use such infinitesimally small values (close to 0.0 but not 0.0) such as the value of B that this value of C suggests. It is impossible that it acquired that value from our data. Can A*B yield anything that is not equal to 0.0 when B is 0?
The number you divided by was not in fact 0, just very, very close.
Assuming you are using IEEE floating point numbers it is not a good idea to use equal or not equal in this case with floating point numbers. Even if the same value like -0.0 and +0.0 they are not equal from a bitwise perspective which is what the equate does. Even if using other float formats, equal and not equal are discouraged.
Instead put some sort of range on it e=a*b; if ((e<0.0002)||(e>0.0002) then...
This looks like you are accruing error from previous calculations, so you divison is by a really small decimal, but not zero. You should add a margin of error if you want to catch something like this, psuedocode: if(num < margin_of_error) ret inf;, or use the epsilon method to be even safer
I'm developing for a platform without a math library, so I need to build my own tools. My current way of getting the fraction is to convert the float to fixed point (multiply with (float)0xFFFF, cast to int), get only the lower part (mask with 0xFFFF) and convert it back to a float again.
However, the imprecision is killing me. I'm using my Frac() and InvFrac() functions to draw an anti-aliased line. Using modf I get a perfectly smooth line. With my own method pixels start jumping around due to precision loss.
This is my code:
const float fp_amount = (float)(0xFFFF);
const float fp_amount_inv = 1.f / fp_amount;
inline float Frac(float a_X)
{
return ((int)(a_X * fp_amount) & 0xFFFF) * fp_amount_inv;
}
inline float Frac(float a_X)
{
return (0xFFFF - (int)(a_X * fp_amount) & 0xFFFF) * fp_amount_inv;
}
Thanks in advance!
If I understand your question correctly, you just want the part after the decimal right? You don't need it actually in a fraction (integer numerator and denominator)?
So we have some number, say 3.14159 and we want to end up with just 0.14159. Assuming our number is stored in float f;, we can do this:
f = f-(long)f;
Which, if we insert our number, works like this:
0.14159 = 3.14159 - 3;
What this does is remove the whole number portion of the float leaving only the decimal portion. When you convert the float to a long, it drops the decimal portion. Then when you subtract that from your original float, you're left with only the decimal portion. We need to use a long here because of the size of the float type (8 bytes on most systems). An integer (only 4 bytes on many systems) isn't necessarily large enough to cover the same range of numbers as a float, but a long should be.
As I suspected, modf does not use any arithmetic per se -- it's all shifts and masks, take a look here. Can't you use the same ideas on your platform?
I would recommend taking a look at how modf is implemented on the systems you use today. Check out uClibc's version.
http://git.uclibc.org/uClibc/tree/libm/s_modf.c
(For legal reasons, it appears to be BSD licensed, but you'd obviously want to double check)
Some of the macros are defined here.
There's a bug in your constants. You're basically trying to do a left shift of the number by 16 bits, mask off everything but the lower bits, then right shift by 16 bits again. Shifting is the same as multiplying by a power of 2, but you're not using a power of 2 - you're using 0xFFFF, which is off by 1. Replacing this with 0x10000 will make the formula work as intended.
I'm not completly sure, but I think that what you are doing is wrong, since you are only considering the mantissa and forgetting the exponent completely.
You need to use the exponent to shift the value in the mantissa to find the actual integer part.
For a description of the storage mechanism of 32bit floats, take a look here.
Why go to floating point at all for your line drawing? You could just stick to your fixed point version and use an integer/fixed point based line drawing routine instead - Bresenham's comes to mind. While this version isn't aliased, I know there are others that are.
Bresenham's line drawing
Seems like maybe you want this.
float f = something;
float fractionalPart = f - floor(f);
Your method is assuming that there are 16 bits in the fractional part (and as Mark Ransom notes, that means you should shift by 16 bits, i.e. multiply by by 0x1000). That might not be true. The exponent is what determines how many bit there are in the fractional part.
To put this in a formula, your method works by calculating (x modf 1.0) as ((x << 16) mod 1<<16) >> 16, and it's that hardcoded 16 which should depend on the exponent - the exact replacement depends on your float format.
double frac(double val)
{
return val - trunc(val);
}
// frac(1.0) = 1.0 - 1.0 = 0.0 correct
// frac(-1.0) = -1.0 - -1.0 = 0.0 correct
// frac(1.4) = 1.4 - 1.0 = 0.4 correct
// frac(-1.4) = -1.4 - -1.0 = -0.4 correct
Simple and works for -ve and +ve
One option is to use fmod(x, 1).