Чому мій розрахунок кольору неба в Mathematica невірний?


17

Я намагаюся реалізувати алгоритм для обчислення кольору неба на основі цієї роботи (модель Переса). Перш ніж почати програмувати шейдер, я хотів перевірити цю концепцію в Mathematica. Вже є деякі проблеми, від яких я не можу позбутися. Можливо, хтось уже реалізував алгоритм.

Я почав з рівняннями для абсолютних zenital яркостей Yz, xzі yzяк це було запропоновано в роботі (сторінка 22). Значення для Yzздаються розумними. На наступній схемі показано Yzфункцію зенітної відстані Сонця від помутніння T5:

Yz (z)

Функціональна гамма (зеніт, азимут, соларзеніт, соларазимут) обчислює кут між точкою із заданою зенітною відстані та азимутом та сонцем у заданому положенні. Ця функція, здається, теж працює. На наступній схемі показаний цей кут для solarzenith=0.5та solarazimuth=0. zenithросте зверху вниз (0 до Pi / 2), azimuthросте зліва направо (-Pi до Pi). Ви чітко бачите положення сонця (яскрава пляма, кут стає нульовим):

гамма (зеніт, азимут, 0,5,0)

Функція Переса (F) та коефіцієнти реалізовані, як зазначено в статті. Тоді значення кольорів повинні бути Yxy absolute value * F(z, gamma) / F(0, solarzenith). Я очікую, що ці значення будуть в межах [0,1]. Однак це не стосується компонента Y (детальніше див. Оновлення нижче). Ось деякі значення вибірки:

{Y, x, y}
{19.1548, 0.25984, 0.270379}
{10.1932, 0.248629, 0.267739]
{20.0393, 0.268119, 0.280024}

Ось поточний результат:

RGB-зображення

Зошит Mathematica з усіма розрахунками можна знайти тут, а версію PDF тут .

Хтось має уявлення про те, що я повинен змінити, щоб отримати ті ж результати, що і в роботі?

C як код

// this function returns the zenital Y component for 
// a given solar zenital distance z and turbidity T
float Yz(float z, float T)
{
    return (4.0453 * T - 4.9710)*tan( (4.0f/9-T/120)*(Pi-2*z) ) - 0.2155 * T + 2.4192
}

// returns zenital x component
float xz(float z, float T)
{
    return //matrix calculation, see paper
}

// returns zenital y component
float yz(float z, float T)
{
    return //matrix calculation, see paper
}

// returns the rgb color of a Yxy color
Color RGB(float Y, float x, float y)
{
    Matrix m; //this is a CIE XYZ -> RGB conversion matrix
    Vector v;
    v.x = x/y*Y;
    v.y = Y;
    v.z = (1-x-y)/y*Y;
    v = M * v; //matrix-vector multiplication;
    return Color ( v.x, v.y, v.z );        
}

// returns the 5 coefficients (A-E) for the given turbidity T
float[5] CoeffY(float T)
{
    float[5] result;
    result[0] = 0.1787 * T - 1.4630;
    result[1] = -0.3554 * T + 0.4275;
    ...
    return result;
}

//same for Coeffx and Coeffy

// returns the angle between an observed point and the sun
float PerezGamma(float zenith, float azimuth, float solarzenith, float solarazimuth)
{
    return acos(sin(solarzenith)*sin(zenith)*cos(azimuth-solarazimuth)+cos(solarzenith)*cos(zenith));
}

// evalutes Perez' function F
// the last parameter is a function
float Perez(float zenith, float gamma, float T, t->float[5] coeffs)
{
    return (1+coeffs(T)[0] * exp(coeffs(T)[1]/cos(zenith)) *
           (1+coeffs(T)[2] * exp(coeffs(T)[3]*gamma) + 
            coeffs(T)[4]*pow(cos(gamma),2))
}

// calculates the color for a given point
YxyColor calculateColor(float zenith, float azimuth, float solarzenith, float solarazimuth, float T)
{
    YxyColor c;
    float gamma = PerezGamma(zenith, azimuth, solarzenith, solarazimuth);
    c.Y = Yz(solarzenith, T) * Perez(zenith, gamma, T, CoeffY) / Perez(0, solarzenith, T, CoeffY);
    c.x = xz(solarzenith, T) * Perez(zenith, gamma, T, Coeffx) / Perez(0, solarzenith, T, Coeffx);
    c.y = yz(solarzenith, T) * Perez(zenith, gamma, T, Coeffy) / Perez(0, solarzenith, T, Coeffy); 
    return c;
}

// draws an image of the sky
void DrawImage()
{
    for(float z from 0 to Pi/2) //zenithal distance
    {
        for(float a from -Pi to Pi) //azimuth
        {
            YxyColor c = calculateColor(zenith, azimuth, 1, 0, 5);
            Color rgb = RGB(c.Y, c.x, c.y);
            setNextColor(rgb);
        }
        newline();
    }
}

Рішення

Як обіцяв, я написав статтю в блозі про візуалізацію неба. Ви можете знайти його тут .


Я підозрюю, що більше людей тут зможуть допомогти вам, якби ви намагалися реалізувати алгоритм у фактичному коді (шейдері чи іншим чином) замість Mathematica.
Тетрад

2
Є Mathematica SE , хоча вам доведеться перевірити їхні FAQ, щоб побачити, чи є ваше питання там на тему.
MichaelHouse

Ну, питання стосується насправді не до математики, а до алгоритму. Я додав версію ноутбука PDF, щоб кожен міг його прочитати. Я впевнений, що синтаксис зрозумілий для звичайного програміста і, ймовірно, більш зрозумілий, ніж шейдерний код.
Ніко Шертлер

@NicoSchertler: Проблема в тому, що я не думаю, що багато людей тут розуміють синтаксис Mathematica. Ймовірно, вам пощастить, якщо ви перепишете свій код на C-подібній або Python-подібній мові, принаймні для цілей цього питання.
Піжама Panda

2
Питання дійсно занадто локалізоване і може закритися, але дякую за паперове посилання, це цікаво.
sam hocevar

Відповіді:


4

У матриці, яка використовується, є дві помилки xz: 1.00166 має бути 0,00166, а 0,66052 - 0,06052.


Дякуємо за виправлення. Зараз результат виглядає краще, але не може бути правильним. Буду вдячний, якщо ви розглянете оновлене запитання.
Ніко Шертлер

-2

Здається, це може бути проблемою масштабування значення кольору?


2
Хоча ваше припущення може бути правильним, було б корисніше надати додаткові пояснення. Оскільки ви не можете відповісти на все запитання, те, що ви написали, має бути коментарем до цього питання.
danijar

Це не дає відповіді на запитання. Щоб критикувати або вимагати роз'яснення у автора, залиште коментар під їх публікацією - ви завжди можете коментувати свої власні публікації, і як тільки у вас буде достатня репутація, ви зможете коментувати будь-яку публікацію .
MichaelHouse

1
Я не розумію, чому пропозиції тут взагалі не приймаються. Якщо ви подивитесь на рішення вище, це питання вартості. Направлення людей у ​​правильному напрямку - це кращий спосіб навчитися, ніж постійно давати точні рішення, чи не так? І ні, я не можу коментувати його питання, тому що мені не дозволено. Ось чому я тут прокоментував. Але дякую за демот. Дуже приємно до вас і дуже заохочує нових людей, як я. Дякую.
boobami
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.