Я пытаюсь создать равномерные случайные точки на поверхности единичной сферы для программы трассировки лучей Монте-Карло. Когда я говорю "равномерное", я имею в виду, что точки равномерно распределены по площади поверхности. Моя нынешняя методология заключается в вычислении однородных случайных точек на полусфере, указывающих на положительную ось z и базу в плоскости x-y.
Случайная точка в полусфере представляет собой направление излучения теплового излучения для диффузного серого излучателя.
Я получаю правильный результат, когда использую следующий расчет:
Примечание: dsfmt * возвращает случайное число от 0 до 1.
azimuthal = 2*PI*dsfmt_genrand_close_open(&dsfmtt);
zenith = asin(sqrt(dsfmt_genrand_close_open(&dsfmtt)));
// Calculate the cartesian point
osRay.c._x = sin(zenith)*cos(azimuthal);
osRay.c._y = sin(zenith)*sin(azimuthal);
osRay.c._z = cos(zenith);
Однако это довольно медленно, и профилирование показывает, что на него приходится большая часть времени выполнения. Поэтому я искал альтернативные методы:
Метод отклонения Марсалья 1972 года
do {
x1 = 2.0*dsfmt_genrand_open_open(&dsfmtt)-1.0;
x2 = 2.0*dsfmt_genrand_open_open(&dsfmtt)-1.0;
S = x1*x1 + x2*x2;
} while(S > 1.0f);
osRay.c._x = 2.0*x1*sqrt(1.0-S);
osRay.c._y = 2.0*x2*sqrt(1.0-S);
osRay.c._z = abs(1.0-2.0*S);
Расчет аналитических декартовых координат
azimuthal = 2*PI*dsfmt_genrand_close_open(&dsfmtt);
u = 2*dsfmt_genrand_close_open(&dsfmtt) -1;
w = sqrt(1-u*u);
osRay.c._x = w*cos(azimuthal);
osRay.c._y = w*sin(azimuthal);
osRay.c._z = abs(u);
Хотя эти последние два метода работают с серварами быстрее, чем первые, когда я их использую, я получаю результаты, которые указывают на то, что они не генерируют однородные случайные точки на поверхности сферы, а скорее дают распределение, которое способствует экватору.
Кроме того, последние два метода дают одинаковые конечные результаты, однако я уверен, что они неверны, поскольку я сравниваю их с аналитическим решением.
Каждая найденная ссылка указывает, что эти методы производят равномерные распределения, но я не достигаю правильного результата.
Есть ли ошибка в моей реализации или я пропустил фундаментальную идею во втором и третьем методах?