Чому мій розрахунок кольору неба в 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.