ทำไมการคำนวณสีท้องฟ้าของฉันใน Mathematica ไม่ถูกต้อง


17

ฉันกำลังพยายามใช้อัลกอริทึมในการคำนวณสีของท้องฟ้าตามบทความนี้ (แบบจำลองของเปเรซ) ก่อนที่ฉันจะเริ่มโปรแกรม shader ฉันต้องการทดสอบแนวคิดใน Mathematica มีปัญหาบางอย่างที่ฉันไม่สามารถกำจัดได้ อาจมีบางคนใช้งานอัลกอริทึมไปแล้ว

ฉันเริ่มต้นด้วยสมการสำหรับ luminances zenital แน่นอนYz, xzและyzตามที่เสนอในกระดาษ (หน้า 22) ค่าสำหรับYzดูเหมือนจะสมเหตุสมผล แผนภาพต่อไปนี้แสดงให้เห็นYzว่าเป็นฟังก์ชั่นของระยะทางของดวงอาทิตย์สำหรับความขุ่นT5:

yz (z)

ฟังก์ชันแกมม่า (สุดยอด, azimuth, solarzenith, solarazimuth) คำนวณมุมระหว่างจุดที่มีระยะทางสูงสุดที่กำหนดและ azimuth และดวงอาทิตย์ที่ตำแหน่งที่กำหนด ฟังก์ชั่นนี้ใช้งานได้ดีเช่นกัน แสดงให้เห็นแผนภาพต่อไปนี้มุมนี้และsolarzenith=0.5 เติบโตจากบนลงล่าง (0 ถึง Pi / 2), เติบโตจากซ้ายไปขวา (-Pi ถึง Pi) คุณสามารถเห็นตำแหน่งของดวงอาทิตย์ได้อย่างชัดเจน (จุดสว่างมุมกลายเป็นศูนย์):solarazimuth=0zenithazimuth

แกมมา (สุดยอดราบ, 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();
    }
}

วิธีการแก้

ฉันสัญญาว่าจะเขียนบทความในบล็อกเกี่ยวกับการแสดงท้องฟ้า คุณสามารถค้นหาได้ที่นี่


ฉันสงสัยว่ามีผู้คนมากมายที่นี่จะสามารถช่วยคุณได้ถ้าคุณพยายามใช้อัลกอริทึมในรหัสจริง (shader หรืออื่น ๆ ) แทนที่จะเป็นใน Mathematica
Tetrad

2
มีMathematica SEแม้ว่าคุณจะต้องตรวจสอบคำถามที่พบบ่อยของพวกเขาเพื่อดูว่าคำถามของคุณอยู่ในหัวข้อที่นั่น
MichaelHouse

คำถามไม่ได้เกี่ยวกับ Mathematica แต่เกี่ยวกับอัลกอริทึม ฉันเพิ่มสมุดบันทึกเวอร์ชัน PDF เพื่อให้ทุกคนสามารถอ่านได้ ฉันแน่ใจว่าไวยากรณ์นั้นเข้าใจได้สำหรับโปรแกรมเมอร์ทั่วไปและอาจเข้าใจได้ง่ายกว่าโค้ด shader
Nico Schertler

@NicoSchertler: ปัญหาคือฉันไม่คิดว่าหลายคนในที่นี่เข้าใจไวยากรณ์ Mathematica คุณอาจจะโชคดีกว่าถ้าคุณเขียนโค้ดในภาษา C-like หรือ Python-like อย่างน้อยที่สุดก็เพื่อจุดประสงค์ของคำถามนี้
แพนด้า Pajama

2
คำถามเป็นภาษาท้องถิ่นมากเกินไปและอาจถูกปิด แต่ขอบคุณสำหรับลิงค์กระดาษมันน่าสนใจ
sam hocevar

คำตอบ:


4

มีข้อผิดพลาดสองอย่างในเมทริกซ์ที่ใช้สำหรับxz: 1.00166 ควรเป็น 0.00166 และ 0.6052 ควรเป็น 0.06052


ขอบคุณสำหรับการแก้ไข ผลลัพธ์ตอนนี้ดูดีขึ้น แต่ไม่ถูกต้อง ฉันจะขอบคุณถ้าคุณพิจารณาคำถามที่ปรับปรุงแล้ว
Nico Schertler

-2

ดูเหมือนว่ามันอาจเป็นปัญหาการปรับขนาดค่าสี?


2
แม้ว่าข้อสันนิษฐานของคุณอาจถูกต้อง แต่ก็มีประโยชน์มากกว่าที่จะให้คำอธิบายเพิ่มเติม เนื่องจากคุณไม่สามารถตอบคำถามทั้งหมดสิ่งที่คุณเขียนควรเป็นความคิดเห็นภายใต้คำถาม
danijar

สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม จะวิจารณ์หรือการร้องขอคำชี้แจงจากผู้เขียนแสดงความคิดเห็นด้านล่างโพสต์ของพวกเขา - คุณสามารถแสดงความคิดเห็นในโพสต์ของคุณเองและเมื่อคุณมีเพียงพอชื่อเสียงคุณจะสามารถที่จะแสดงความคิดเห็นในโพสต์ใด
MichaelHouse

1
ฉันไม่เข้าใจว่าทำไมถึงไม่ยอมให้มีการแนะนำที่นี่เลย หากคุณดูวิธีการแก้ปัญหาข้างต้นจะเป็นปัญหาค่า การชี้คนในทิศทางที่ถูกต้องเป็นวิธีที่ดีกว่าในการเรียนรู้มากกว่าการให้คำตอบที่ถูกต้องตลอดเวลาใช่ไหม และไม่ฉันไม่สามารถแสดงความคิดเห็นด้านล่างคำถามของเขาเพราะฉันไม่ได้รับอนุญาต นี่คือเหตุผลที่ฉันแสดงความคิดเห็นที่นี่ แต่ขอบคุณสำหรับการลดระดับ คุณดีมากและให้กำลังใจกับคนใหม่อย่างฉัน ขอขอบคุณ.
boobami
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.