为什么在Mathematica中我的天空颜色计算不正确?


17

我正在尝试根据本文(Perez模型)实现一种算法来计算天空颜色。在开始对着色器进行编程之前,我想在Mathematica中测试该概念。已经存在一些我无法摆脱的问题。也许有人已经实现了该算法。

我首先从绝对绝对亮度的方程式开始Yzxzyz按照论文的建议(第22页)进行了计算。的值Yz似乎是合理的。下图显示Yz了浊度T为5时太阳的距离的函数:

Yz(z)

函数gamma(天顶,方位角,太阳斜角,太阳脊)计算具有给定的距离和方位角的点与给定位置的太阳之间的角度。此功能似乎也起作用。下图显示了solarzenith=0.5和的角度solarazimuth=0zenith从上到下(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实现算法,那么这里会有更多的人可以为您提供帮助。
Tetrad

2
有一个Mathematica SE,尽管您必须检查他们的FAQ,以查看您的问题是否在那边。
迈克尔豪斯

好吧,问题不是关于Mathematica的,而是关于算法的。我添加了笔记本的PDF版本,因此每个人都可以阅读。我确信该语法对于普通程序员来说是可以理解的,并且可能比着色器代码更容易理解。
Nico Schertler 2013年

@NicoSchertler:问题是我认为这里的人并不了解Mathematica语法。如果至少使用C语言或Python语言重写代码,可能会更幸运。
熊猫睡衣

2
这个问题确实太局限了,可能会解决,但是感谢您的论文链接,这很有趣。
sam hocevar

Answers:


4

矩阵中存在两个误差xz:1.00166应该是0.00166,而0.6052应该是0.06052。


感谢您的更正。现在,结果看起来更好,但是不正确。如果您考虑更新的问题,将不胜感激。
Nico Schertler 2013年

-2

好像是颜色值缩放问题?


2
尽管您的假设可能是正确的,但提供更多的解释会更有用。由于您无法回答整个问题,因此您写的内容应该是该问题下的注释。
danijar

这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论-您可以随时对自己的帖子发表评论,一旦您拥有足够的声誉,就可以在任何帖子中发表评论
MichaelHouse

1
我不明白为什么这里根本不容忍建议。如果您看上面的解决方案,那是一个价值问题。与始终提供精确的解决方案相比,向人们指明正确的方向是更好的学习方法,不是吗?不,我不能在他的问题下方发表评论,因为不允许我这样做。这就是为什么我在这里评论。但是感谢降级。你们真是太好了,并且对像我这样的新人很鼓舞。谢谢。
boobami
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.