POV-Ray : Newsgroups : povray.off-topic : Random vector through a hemisphere? Server Time
4 Nov 2024 19:18:58 EST (-0500)
  Random vector through a hemisphere? (Message 1 to 10 of 15)  
Goto Latest 10 Messages Next 5 Messages >>>
From: Severi Salminen
Subject: Random vector through a hemisphere?
Date: 17 Feb 2008 06:15:13
Message: <47b81741$1@news.povray.org>
I'm trying to create a random uniformly distributed vector through a
hemisphere positioned at the intersection point between ray and an
object. I can already create a random vector but how do I quickly/easily
rotate it based on the desired hemisphere orientation?

I use left-handed coordinate system: x is right, y is up, and z is forward.

Let's have a vector V which is random vector inside a hemisphere which
has a pole at 0,1,0 (just like the northern hemisphere of Earth). I want
to orient the vector inside a hemisphere which has a pole pointing at
vector N. How do I do this? I'd prefer something that can be done
without expensive trigonometric functions or complex transformations -
if possible.

Example:

V = (0.71, 0.71, 0) //The random vector in "northern hemishpere")
N = (-1,0,0) //The pole I want to orientate the random vectors to)

The result should be like this or any other vector that results the same
distribution:

Vnew = (-0.71, 0.71, 0)

Any ideas? I got one idea from comp.graphics.algorithms but it doesn't
seem to work properly:

Vnew = Vec (dot (V, S), dot (V, N), dot (V, T))

Where N = normal, V the initial random vector in northern hemisphere, S
and T are tangents of the normal orthogonal to each other.


Post a reply to this message

From: Severi Salminen
Subject: Re: Random vector through a hemisphere?
Date: 17 Feb 2008 07:28:15
Message: <47b8285f@news.povray.org>
Severi Salminen wrote:
> I'm trying to create a random uniformly distributed vector through a
> hemisphere positioned at the intersection point between ray and an
> object. I can already create a random vector but how do I quickly/easily
> rotate it based on the desired hemisphere orientation?

I found the answer in this thread. The equation in my first message
really seems to be incorrect:

http://news.povray.org/povray.programming/thread/%3Cweb.453fedef87fb35ab5dbe37df0@news.povray.org%3E/


Post a reply to this message

From: John VanSickle
Subject: Re: Random vector through a hemisphere?
Date: 17 Feb 2008 13:17:46
Message: <47b87a4a@news.povray.org>
Another way is to generate a random vector:

#local vResult=vrotate(x,<rand(Seed),rand(Seed),rand(Seed)>*360);

#if(vdot(vResult,vN)<0)
   #local vResult=-vResult;
#end

Basically, generate a random vector, and if it's in the wrong 
hemisphere, flip its direction.

Regards,
John


Post a reply to this message

From: scott
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 03:10:13
Message: <47b93d65$1@news.povray.org>
> Another way is to generate a random vector:
>
> #local vResult=vrotate(x,<rand(Seed),rand(Seed),rand(Seed)>*360);

vResult is not uniformly distributed over the sphere with this approach 
though...


Post a reply to this message

From: Severi Salminen
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 03:38:27
Message: <47b94403@news.povray.org>
scott wrote:
>> Another way is to generate a random vector:
>>
>> #local vResult=vrotate(x,<rand(Seed),rand(Seed),rand(Seed)>*360);
> 
> vResult is not uniformly distributed over the sphere with this approach
> though...

I use this:

y = sqrt(rand(0..1))
theta = acos(y)
phi = 2*PI*rand(0..1)

x = sin(theta)*cos(phi)
z = sin(theta)*sin(phi)

What I don't get is the sqrt(rand()). Why sqrt? Why not just rnd()? Does
the sqrt give us the cosine distribution and should remove the need to
later scale by taking cosine of the angle between normal and the light ray?


Post a reply to this message

From: scott
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 03:57:27
Message: <47b94877$1@news.povray.org>
> I use this:
>
> y = sqrt(rand(0..1))
> theta = acos(y)
> phi = 2*PI*rand(0..1)
>
> x = sin(theta)*cos(phi)
> z = sin(theta)*sin(phi)
>
> What I don't get is the sqrt(rand()). Why sqrt? Why not just rnd()? Does
> the sqrt give us the cosine distribution and should remove the need to
> later scale by taking cosine of the angle between normal and the light 
> ray?

No, you are simply choosing a fixed Y position, which then defines a ring 
around the sphere of possible points.  Then phi is used to choose a point at 
random on this ring which gives you the final point.

The reason for using sqrt for y is because you want points equally 
distributed over the surface of the sphere, not between y=0 to 1.  You can 
visualise this by drawing a straight line alongside a circle.  If you 
distribute points evenly on the line, then trace them across to the circle, 
they won't be distributed evenly on the circle.  The sqrt fixes that.


Post a reply to this message

From: Severi Salminen
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 05:12:33
Message: <47b95a11@news.povray.org>
>> y = sqrt(rand(0..1))
>> theta = acos(y)
>> phi = 2*PI*rand(0..1)
>>
>> x = sin(theta)*cos(phi)
>> z = sin(theta)*sin(phi)

> The reason for using sqrt for y is because you want points equally
> distributed over the surface of the sphere, not between y=0 to 1.

Hmm. Ok. I think I got it. So without sqrt() we get too few rays going
through the top part? A few more questions.

1. Is this equally good as the above - at least it looks to be. And a
bit faster.

    double y = sqrt((double) rand()/RAND_MAX);
    double phi = 2*M_PI* (double)rand()/RAND_MAX;
    double x = sqrt(1-y*y)*cos(phi);
    double z = sqrt(1-y*y)*sin(phi);


What is the proper way to actually test the uniformity?

2. I read about "cosine weighted distribution" which should remove the
need to scale with cosine term. This sounds ideal solution. But
according tho this:

http://www.cs.kuleuven.be/~phil/GI/TotalCompendium.pdf

"Generating points uniformly on the disk (see 19), and then projecting
them on the hemisphere, also gives a cosine-weighted distribution of
points on the hemisphere."

I also tried that:


    do{
        x = (double) 2.0*rand()/RAND_MAX -1.0;
        z = (double) 2.0*rand()/RAND_MAX-1.0;
    }
    while(x*x+z*z > 1.0);

    y = sqrt(1.0-(x*x+z*z));

And the results are very close to the 2 other methods.

This is what I read from comp.graphics.algorithms:

"One other way to reduce variance in this situation is to shoot rays
with a cosine-weighted distribution. Generate points distributed
uniformly on the unit disk, then project up to the unit
hemisphere. Each point will define a ray drawn from the proper
distribution. Then, at least for the indirect lighting, you don't need
to include the cosine explicitly at all. But that's not the real win:
the win is that each sample actually contains more information about
the mean value, so variance will be less with the same number of rays."

So what is the truth here? Do I need to account the angle of the ray or
not?


Post a reply to this message

From: Severi Salminen
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 05:15:35
Message: <47b95ac7$1@news.povray.org>
Severi Salminen wrote:

> I also tried that:
> 
> 
>     do{
>         x = (double) 2.0*rand()/RAND_MAX -1.0;
>         z = (double) 2.0*rand()/RAND_MAX-1.0;
>     }
>     while(x*x+z*z > 1.0);
> 
>     y = sqrt(1.0-(x*x+z*z));
> 
> And the results are very close to the 2 other methods.

And this is also the fastest algorithm of the tree.


Post a reply to this message

From: scott
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 05:34:11
Message: <47b95f23$1@news.povray.org>
> 1. Is this equally good as the above - at least it looks to be. And a
> bit faster.
>
>    double y = sqrt((double) rand()/RAND_MAX);
>    double phi = 2*M_PI* (double)rand()/RAND_MAX;
>    double x = sqrt(1-y*y)*cos(phi);
>    double z = sqrt(1-y*y)*sin(phi);

Looks ok to me.

> What is the proper way to actually test the uniformity?

Either mathematically proving it, or write a test program that measures the 
density of points over the surface.

> I also tried that:
>
>
>    do{
>        x = (double) 2.0*rand()/RAND_MAX -1.0;
>        z = (double) 2.0*rand()/RAND_MAX-1.0;
>    }
>    while(x*x+z*z > 1.0);
>
>    y = sqrt(1.0-(x*x+z*z));
>
> And the results are very close to the 2 other methods.

This result is different to the above and not spread uniformly over the 
surface of the sphere (it is uniform only in the xz plane).


Post a reply to this message

From: Severi Salminen
Subject: Re: Random vector through a hemisphere?
Date: 18 Feb 2008 05:49:58
Message: <47b962d6$1@news.povray.org>
>>    double y = sqrt((double) rand()/RAND_MAX);
>>    double phi = 2*M_PI* (double)rand()/RAND_MAX;
>>    double x = sqrt(1-y*y)*cos(phi);
>>    double z = sqrt(1-y*y)*sin(phi);
> 
> Or:
>
>>    do{
>>        x = (double) 2.0*rand()/RAND_MAX -1.0;
>>        z = (double) 2.0*rand()/RAND_MAX-1.0;
>>    }
>>    while(x*x+z*z > 1.0);
>>
>>    y = sqrt(1.0-(x*x+z*z));
>>
> This result is different to the above and not spread uniformly over the
> surface of the sphere (it is uniform only in the xz plane).

Ok, that makes me wonder, because:

1. The 2 methods above produce 100% identical images. It was a scene of
one light emitting sphere, ground and 3 diffusing spheres of different
colors. (I did use the cosine ratio relative to the angle of light
falling on surface.) I can post the images if needed. The only
difference is that the second method is faster - with a great margin.

2. If the distribution is not identical by the 2 methods, why are the
images still 100% identical?


Post a reply to this message

Goto Latest 10 Messages Next 5 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.