Distributing a variable [0-1] logarithmically

Started by
5 comments, last by __0BZEN__ 7 years, 11 months ago

Hey guys,

I was wondering about this little math problem of mine (which is also something I've come across several times but never had an answer to).

Given is a floating point variable between 0 and 1 evenly distributed (linearly).

However I would like this variable to be distributed logarithmically so that I have more precision in the lower region towards zero.

I've played around with using the log functions which gives me the nice distribution I want however I have no idea how to make it so that it's still between a min and max number, [0,1] in my case.

Any help would be appreciated :)

Advertisement
I don't think what you are asking is technically possible. Do you want the probability of [0.5,1] to be the same as the probability of [0.25,0.5] and the same as the probability of [0.125,0.25] and so on? That's what "logarithmic" sounds like to me. Unfortunately, that means the probability of all of those intervals must necessarily be 0.

Perhaps you could describe what your requirements are or what you intend to do with these numbers.

EDIT: Have you tried a simple power law? Take x in [0,1] and map it to something like x^3. That will probably result in something like what you have in mind. Tweak the exponent to taste.
In the book Texturing and Modeling: A Procedural Approach, one of the authors (I believe it was Perlin) provided two functions he uses to re-distribute values in the unit range:


function bias(t, b) return math.pow(t, math.log(b)/math.log(0.5)) end
function gain(t, g) if t<0.5 then return bias(1.0-g, 2.0*t)/2.0 else return 1.0-bias(1.0-g, 2.0-2.0*t)/2.0 end end
The bias function is used to push values toward one end or the other; values of b less than 0.5 push values of t nearer to 0, while a bias greater than 0.5 push the values toward 1. gain uses bias, and has the effect that if g is less than 0.5, the values are pushed toward the ends, while greater than 0.5 values are pushed toward the middle. In both these functions, 0.5 for the bias or gain factor results in the linear curve. For example:

If the linear curve looks like this:

yPwMxMI.png

then the same curve with bias(0.2) applies looks like this:

ggSo82N.png

bias(0.8) looks like:

5mMhzhR.png

gain(0.2) looks like:

GYu25Pl.png

and gain(0.8) looks like:

EFPJXyv.png

In all cases, if t is in the range 0,1 then the output will also be in the range 0,1.

Basically I want something similar to how a depth buffer is distributed from [0,1]. Have more precision from let's say [0, 0.5] and less from [0.5, 1.0].

I want to have this for a slider UI element where I need to tweak a variable in the [0,1] range but need more fine grain control over the first lower range than the higher range.

Hmm you might be right I could try using a power function...

@JTippetts That is awesome, I'll try that out asap

a power function should do. The range will stay [0,1], but the curve/distribution will change.

however, keep in mind that you cannot really rasterize in non linear space, hence you need to do the depth conversion in pixelshader.

Using a power function like the one described by JTippetts works perfectly, thank you !

For some reason I was thinking about a log function but completely forgot that the pow function is the one I was looking for.

@Krypt0n I was just using the depth buffer behavior as an example, the usage for this is for a more general functionality (e.g. more fine grained control over parameters in UI element sliders)

That's the kind of things sometimes seen in inputs. And yeah, power functions. The rationale is simple. X in range ]0, ...], 0 pow(X) = 0, 1 pow(X) = 1, anything in between is in the range [0, 1], continuous.

This topic is closed to new replies.

Advertisement