Exemplo n.º 1
0
Colorf Sky::getRadianceAt(float theta, float phi, bool checkerboard) {
	if(checkerboard) {
		const int x = theta / (pi / 5);
		const int y = phi / (pi / 5);

		const int parity = (x ^ y) % 2;
		const float val = parity ? 150 : 100;

		return Colorf(val, val, val);
	}

	if(theta > pi / 2) {
		return Colorf(0, 0, 0);
	}

	// Preetham sky model
	// http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
	//
	// Hints for reading the paper:
	// * we don't consider object light scattering
	//   (maybe needed later when considering far-away moutains or such)
	// * when there's no object, L(0) = 0 (universe background)
	// * don't get distracted by approximations for hand-calculation
	//   (it's simpler (and more flexible) to do numerical calc + smart memoization)
	const float view_height = 0;

	const float alpha_haze = 0.8333;  // haze: /km
	const float alpha_mole = 0.1136;  // molecules: /km

	const Eigen::Vector3f view_direction(
		std::sin(theta) * std::cos(phi),
		std::sin(theta) * std::sin(phi),
		std::cos(theta));	

	// Based on Nishita's 1st-order scattering sky model.
	// We ignore point-to-space decay.
	Colorf radiance(0, 0, 0);
	Colorf decay_here_to_view(1, 1, 1);
	for(int i = 0; i < 50; i++) {
		const float distance = i;
		const float height = distance * std::cos(theta) + view_height;

		//
		const float cos_view_sun = view_direction.dot(sun_direction);

		// Calculate scattering
		// Mie scattering's phase function is not well-described anywhere.
		// But it's said to be very sharp. So
		// we use (1+cos^3 theta)^2/4
		// (http://www.wolframalpha.com/input/?i=plot+r%3D%281%2Bcos%5E3+theta%29%5E2%2F4)
		const Colorf scatter =
			particleDensity(alpha_mole, distance, theta) * rayleigh(cos_view_sun) +
			particleDensity(alpha_haze, distance, theta) * mie(cos_view_sun);

		// Note. decay_space_to_here and decay_here_to_view are not colinear.
		radiance += sun_power
			.cwiseProduct(scatter)
			.cwiseProduct(decay_here_to_view);

		const Colorf decay_scatter =
			particleDensity(alpha_mole, distance, theta) * rayleighTotal() +
			particleDensity(alpha_haze, distance, theta) * mieTotal();

		decay_here_to_view = decay_here_to_view.cwiseProduct(
			Colorf(1, 1, 1) - decay_scatter);
	}
	assert(radiance[0] >= 0 && radiance[1] >= 0 && radiance[2] >= 0);
	radiance /= 100;
	return radiance;
}
Exemplo n.º 2
0
/*
  To compute the optical scattering parameters (extinction and scattering
  coefficients, single scattering albedo, phase function, assymetry factor) at the ten discrete
  wavelengths for the selected model (or created model) from:
  (1) the characteristics of the basic components of the International Radiation Commission.
  (1983).
  dust-like component (D.L., SUBROUTINE DUST)
  oceanic component (O.C., SUBROUTINE OCEA)
  water-soluble component (W.S., SUBROUTINE WATE)
  soot component (S.O., SUBROUTINE SOOT)
  (2) pre-computed caracteristics,
  now available are the desertic aerosol model corresponding to background conditions, as
  described in Shettle(1984), a stratospheric aerosol model as measured Mona Loa (Hawaii)
  during El Chichon eruption and as described by King et al. (1984), and a biomass burning
  aerosol model as deduced from measurements taken by sunphotometers in Amazonia.
  (SUBROUTINES BDM, STM and BBM)
  (3) computed using the MIE theory with inputs (size distribution, refractive indexes...) given
  by the user (see SUBROUTINES MIE and EXSCPHASE).
  These models don't correspond to a mixture of the four basic components.
*/
void AerosolModel::aeroso(const float xmud)
{
    /* sra basic components for aerosol model, extinction coefficients are */
    /* in km-1. */
    /*     dust-like = 1 */
    /*     water-soluble = 2 */
    /*     oceanique = 3 */
    /*     soot = 4 */
    static const double vi[4] = { 113.983516, 1.13983516e-4, 5.1444150196, 5.977353425e-5 };
    static const double ni[4] = { 54.734, 1868550., 276.05, 1805820. };

    /* i: 1=dust-like 2=water-soluble 3=oceanic 4=soot */
    static const float s_ex[4][10] =
    {
        {   0.1796674e-01,0.1815135e-01,0.1820247e-01,0.1827016e-01,0.1842182e-01,
            0.1853081e-01,0.1881427e-01,0.1974608e-01,0.1910712e-01,0.1876025e-01
        },
        {   0.7653460e-06,0.6158538e-06,0.5793444e-06,0.5351736e-06,0.4480091e-06,
            0.3971033e-06,0.2900993e-06,0.1161433e-06,0.3975192e-07,0.1338443e-07
        },
        {   0.3499458e-02,0.3574996e-02,0.3596592e-02,0.3622467e-02,0.3676341e-02,
            0.3708866e-02,0.3770822e-02,0.3692255e-02,0.3267943e-02,0.2801670e-02
        },
        {   0.8609083e-06,0.6590103e-06,0.6145787e-06,0.5537643e-06,0.4503008e-06,
            0.3966041e-06,0.2965532e-06,0.1493927e-06,0.1017134e-06,0.6065031e-07
        }
    };

    static const float s_sc[4][10] =
    {
        {   0.1126647e-01,0.1168918e-01,0.1180978e-01,0.1196792e-01,0.1232056e-01,
            0.1256952e-01,0.1319347e-01,0.1520712e-01,0.1531952e-01,0.1546761e-01
        },
        {   0.7377123e-06,0.5939413e-06,0.5587120e-06,0.5125148e-06,0.4289210e-06,
            0.3772760e-06,0.2648252e-06,0.9331806e-07,0.3345499e-07,0.1201109e-07
        },
        {   0.3499455e-02,0.3574993e-02,0.3596591e-02,0.3622465e-02,0.3676338e-02,
            0.3708858e-02,0.3770696e-02,0.3677038e-02,0.3233194e-02,0.2728013e-02
        },
        {   0.2299196e-06,0.1519321e-06,0.1350890e-06,0.1155423e-06,0.8200095e-07,
            0.6469735e-07,0.3610638e-07,0.6227224e-08,0.1779378e-08,0.3050002e-09
        }
    };

    static const float ex2[10] =
    {
        43.83631f, 42.12415f, 41.57425f, 40.85399f, 39.1404f,
        37.89763f, 34.67506f, 24.59f, 17.96726f, 10.57569f
    };

    static const float sc2[10] =
    {
        40.28625f, 39.04473f, 38.6147f, 38.03645f, 36.61054f,
        35.54456f, 32.69951f, 23.41019f, 17.15375f,10.09731f
    };

    static const float ex3[10] =
    {
        95397.86f, 75303.6f, 70210.64f, 64218.28f, 52430.56f,
        45577.68f, 31937.77f, 9637.68f, 3610.691f, 810.5614f
    };

    static const float sc3[10] =
    {
        92977.9f, 73397.17f, 68425.49f,	62571.8f, 51049.87f,
        44348.77f, 31006.21f, 9202.678f, 3344.476f,	664.1915f
    };

    static const float ex4[10] =
    {
        54273040.f, 61981440.f, 63024320.f, 63489470.f, 61467600.f,
        58179720.f, 46689090.f, 15190620.f, 5133055.f, 899859.4f
    };


    static const float sc4[10] =
    {
        54273040.f, 61981440.f, 63024320.f, 63489470.f, 61467600.f,
        58179720.f, 46689090.f, 15190620.f, 5133055.f, 899859.4f
    };

    static const float s_asy[4][10] =
    {
        {0.896,0.885,0.880,0.877,0.867,0.860,0.845,0.836,0.905,0.871},
        {0.642,0.633,0.631,0.628,0.621,0.616,0.610,0.572,0.562,0.495},
        {0.795,0.790,0.788,0.781,0.783,0.782,0.778,0.783,0.797,0.750},
        {0.397,0.359,0.348,0.337,0.311,0.294,0.253,0.154,0.103,0.055}
    };

    static const float asy2[10] = { .718f, .712f, .71f, .708f, .704f, .702f, .696f, .68f, .668f, .649f };

    static const float asy3[10] = { .704f, .69f, .686f, .68f, .667f, .659f, .637f, .541f, .437f, .241f };
    static const float asy4[10] = { .705f, .744f, .751f, .757f, .762f, .759f, .737f, .586f, .372f, .139f };

    /* local */
    double coef;
    float sigm;
    double sumni;
    double dd[4][10];
    double pha[5][10][83];

    float ex[4][10];
    float sc[4][10];
    float asy[4][10];

    int i;	/* crappy VS6 */
    /* initialize ex, sc & asy */
    for(i = 0; i < 4; i++)
    {
        int j;
        for(j = 0; j < 10; j++) ex[i][j] = s_ex[i][j];
        for(j = 0; j < 10; j++) sc[i][j] = s_sc[i][j];
        for(j = 0; j < 10; j++) asy[i][j] = s_asy[i][j];
    }

    /* optical properties of aerosol model computed from sra basic comp */
    for (i = 0; i < 10; ++i)
    {
        if(i == 4 && iaer == 0) sixs_aer.ext[i] = 1.f;
        else sixs_aer.ext[i] = 0.f;
        sca[i] = 0.f;
        sixs_aer.ome[i] = 0.f;
        sixs_aer.gasym[i] = 0.f;
        sixs_aer.phase[i] = 0.f;

        for (int k = 1; k <= 83; ++k) sixs_sos.phasel[i][k] = 0.f;
    }

    /* return if iear = 0 */
    if(iaer == 0) return;

    /* look for an interval in cgaus */
    long int j1 = -1;
    for (i = 0; i < 82; ++i)
        if (xmud >= sixs_sos.cgaus[i] && xmud < sixs_sos.cgaus[i+1])  {
            j1 = i;
            break;
        }
    if(j1 == -1) return; /* unable to find interval */

    coef = -(xmud - sixs_sos.cgaus[j1]) / (sixs_sos.cgaus[j1+1] - sixs_sos.cgaus[j1]);

    switch(iaer)
    {
    case 12: /* read from file */
    {
        load();
        for(i = 0; i < 10; i++)
            sixs_aer.phase[i] = (float)(sixs_sos.phasel[i][j1] +
                                        coef*(sixs_sos.phasel[i][j1]-sixs_sos.phasel[i][j1+1]));
        return;
    }
    case 5:
    {
        for(i = 0; i < 10; i++)
        {
            asy[0][i]	= asy2[i];
            ex[0][i]	= ex2[i];
            sc[0][i]	= sc2[i];
        }
        break;
    }
    case 6:
    {
        for(i = 0; i < 10; i++)
        {
            asy[0][i]	= asy3[i];
            ex[0][i]	= ex3[i];
            sc[0][i]	= sc3[i];
        }
        break;
    }
    case 7:
    {
        for(i = 0; i < 10; i++)
        {
            asy[0][i]	= asy4[i];
            ex[0][i]	= ex4[i];
            sc[0][i]	= sc4[i];
        }
        break;
    }
    default:
        ;
    }


    if(iaer >= 5 && iaer <= 11)
    {
        /* calling a special aerosol model */

        switch(iaer)
        {
        /* (background desert model...) */
        case 5:
            bdm();
            break;
        /* (biomass burning model...) */
        case 6:
            bbm();
            break;
        /* (stratospherique aerosol model...) */
        case 7:
            stm();
            break;

        /* (user defined model from size distribution) */
        case 8:
        case 9:
        case 10:
        case 11:
            mie (ex, sc, asy);
            break;
        }

        for (int i = 0; i < 10; i++)
        {
            dd[0][i] = (*sixs_aerbas.ph)[i][j1] + coef * ((*sixs_aerbas.ph)[i][j1] - (*sixs_aerbas.ph)[i][j1+1]);
            for(int k = 0; k < 83; k++) pha[0][i][k] = (*sixs_aerbas.ph)[i][k];
        }

        mie_in.icp = 1;
        mie_in.cij[0] = 1.f;
        /* for normalization of the extinction coefficient */
        nis = 1. / ex[0][3];
    }
    else {
        /* calling each sra components */
        mie_in.icp = 4;
        /*  -dust */
        dust();
        for(i = 0; i < 10; i++)
        {
            dd[0][i] = (*sixs_aerbas.ph)[i][j1] + coef * ((*sixs_aerbas.ph)[i][j1] - (*sixs_aerbas.ph)[i][j1+1]);
            for(int k = 0; k < 83; k++) pha[0][i][k] = ((*sixs_aerbas.ph))[i][k];
        }

        /* -water soluble */
        wate();
        for(i = 0; i < 10; i++)
        {
            dd[1][i] = (*sixs_aerbas.ph)[i][j1]+coef*((*sixs_aerbas.ph)[i][j1]-(*sixs_aerbas.ph)[i][j1+1]);
            for(int k = 0; k < 83; k++) pha[1][i][k] = (*sixs_aerbas.ph)[i][k];
        }


        /* -oceanic type */
        ocea();
        for(i = 0; i < 10; i++)
        {
            dd[2][i] = (*sixs_aerbas.ph)[i][j1]+coef*((*sixs_aerbas.ph)[i][j1]-(*sixs_aerbas.ph)[i][j1+1]);
            for(int k = 0; k < 83; k++) pha[2][i][k] = (*sixs_aerbas.ph)[i][k];
        }

        /* -soot */
        soot();
        for(i = 0; i < 10; i++)
        {
            dd[3][i] = (*sixs_aerbas.ph)[i][j1]+coef*((*sixs_aerbas.ph)[i][j1]-(*sixs_aerbas.ph)[i][j1+1]);
            for(int k = 0; k < 83; k++) pha[3][i][k] = (*sixs_aerbas.ph)[i][k];
        }

        /* summ of the c/vi calculation */
        sumni = 0.f;
        sigm = 0.f;

        for(i = 0; i < 4; i++) sigm+=(float)(c[i]/vi[i]);

        /* cij coefficients calculation */
        for(i = 0; i < 4; i++) {
            mie_in.cij[i] = (float)(c[i]/vi[i]/sigm);
            sumni += mie_in.cij[i]/ni[i];
        }

        nis = 1. / sumni;
    }


    /*     mixing parameters calculation */
    for(i = 0; i < 10; i++)
    {
        for(int j = 0; j < mie_in.icp; j++)
        {
            sixs_aer.ext[i] +=		(float)(ex[j][i] * mie_in.cij[j]);
            sca[i] +=				(float)(sc[j][i] * mie_in.cij[j]);
            sixs_aer.gasym[i] +=	(float)(sc[j][i] * mie_in.cij[j] * asy[j][i]);
            sixs_aer.phase[i] +=	(float)(sc[j][i] * mie_in.cij[j] * dd[j][i]);

            for(int k = 0; k < 83; k++)
                sixs_sos.phasel[i][k] += (float)(sc[j][i] * mie_in.cij[j] * pha[j][i][k]);
        }

        sixs_aer.ome[i] = sca[i]/sixs_aer.ext[i];
        sixs_aer.gasym[i] /= sca[i];
        sixs_aer.phase[i] /= sca[i];

        for(int k = 0; k < 83; k++)	sixs_sos.phasel[i][k] /= sca[i];

        sixs_aer.ext[i] *= (float)nis;
        sca[i] *= (float)nis;
    }

    if (filename.size() != 0 && iaer >= 8 && iaer <= 11) save();
}
Exemplo n.º 3
0
Colorf Sky::mie(float cos) {
	return Colorf(
		mie(cos, wl_r),
		mie(cos, wl_g),
		mie(cos, wl_b));
}