示例#1
0
	SkyEmitter(Stream *stream, InstanceManager *manager)
		    : Emitter(stream, manager) {
		m_scale = stream->readFloat();
		m_turbidity = stream->readFloat();
		m_stretch = stream->readFloat();
		m_resolution = stream->readInt();
		m_extend = stream->readBool();
		m_albedo = Spectrum(stream);
		m_sun = SphericalCoordinates(stream);

		Float sunElevation = 0.5f * M_PI - m_sun.elevation;
		#if SPECTRUM_SAMPLES == 3
			for (int i=0; i<SPECTRUM_SAMPLES; ++i)
				m_state[i] = arhosek_rgb_skymodelstate_alloc_init(
					m_turbidity, m_albedo[i], sunElevation);
		#else
			for (int i=0; i<SPECTRUM_SAMPLES; ++i)
				m_state[i] = arhosekskymodelstate_alloc_init(
					m_turbidity, m_albedo[i], sunElevation);
		#endif

		configure();
	}
示例#2
0
	SkyEmitter(const Properties &props)
			: Emitter(props) {
		m_scale = props.getFloat("scale", 1.0f);
		m_turbidity = props.getFloat("turbidity", 3.0f);
		m_stretch = props.getFloat("stretch", 1.0f);
		m_resolution = props.getInteger("resolution", 512);
		m_albedo = props.getSpectrum("albedo", Spectrum(0.2f));
		m_sun = computeSunCoordinates(props);
		m_extend = props.getBoolean("extend", false);

		if (m_turbidity < 1 || m_turbidity > 10)
			Log(EError, "The turbidity parameter must be in the range [1,10]!");
		if (m_stretch < 1 || m_stretch > 2)
			Log(EError, "The stretch parameter must be in the range [1,2]!");
		for (int i=0; i<SPECTRUM_SAMPLES; ++i) {
			if (m_albedo[i] < 0 || m_albedo[i] > 1)
				Log(EError, "The albedo parameter must be in the range [0,1]!");
		}

		Float sunElevation = 0.5f * M_PI - m_sun.elevation;

		if (sunElevation < 0)
			Log(EError, "The sun is below the horizon -- this is not supported by the sky model.");

		#if SPECTRUM_SAMPLES == 3
			for (int i=0; i<SPECTRUM_SAMPLES; ++i)
				m_state[i] = arhosek_rgb_skymodelstate_alloc_init(
					m_turbidity, m_albedo[i], sunElevation);
		#else
			for (int i=0; i<SPECTRUM_SAMPLES; ++i)
				m_state[i] = arhosekskymodelstate_alloc_init(
					m_turbidity, m_albedo[i], sunElevation);
		#endif

		configure();
	}
    Float3 SunLuminance(bool& cached)
    {
        Float3 sunDirection = AppSettings::SunDirection;
        sunDirection.y = Saturate(sunDirection.y);
        sunDirection = Float3::Normalize(sunDirection);
        const float turbidity = Clamp(AppSettings::Turbidity.Value(), 1.0f, 32.0f);
        const float intensityScale = AppSettings::SunIntensityScale;
        const Float3 tintColor = AppSettings::SunTintColor;
        const bool32 normalizeIntensity = AppSettings::NormalizeSunIntensity;
        const float sunSize = AppSettings::SunSize;

        static float turbidityCache = 2.0f;
        static Float3 sunDirectionCache = Float3(-0.579149902f, 0.754439294f, -0.308879942f);
        static Float3 luminanceCache = Float3(1.61212531e+009f, 1.36822630e+009f, 1.07235315e+009f);
        static Float3 sunTintCache = Float3(1.0f, 1.0f, 1.0f);
        static float sunIntensityCache = 1.0f;
        static bool32 normalizeCache = false;
        static float sunSizeCache = AppSettings::BaseSunSize;

        if(turbidityCache == turbidity && sunDirection == sunDirectionCache
            && intensityScale == sunIntensityCache && tintColor == sunTintCache
            && normalizeCache == normalizeIntensity && sunSize == sunSizeCache)
        {
            cached = true;
            return luminanceCache;
        }

        cached = false;

        float thetaS = std::acos(1.0f - sunDirection.y);
        float elevation = Pi_2 - thetaS;

        // Get the sun's luminance, then apply tint and scale factors
        Float3 sunLuminance;

        // For now, we'll compute an average luminance value from Hosek solar radiance model, even though
        // we could compute illuminance directly while we're sampling the disk
        SampledSpectrum groundAlbedoSpectrum = SampledSpectrum::FromRGB(GroundAlbedo);
        SampledSpectrum solarRadiance;

        const uint64 NumDiscSamples = 4;
        for(uint64 x = 0; x < NumDiscSamples; ++x)
        {
            for(uint64 y = 0; y < NumDiscSamples; ++y)
            {
                float u = (x + 0.5f) / NumDiscSamples;
                float v = (y + 0.5f) / NumDiscSamples;
                Float2 discSamplePos = SquareToConcentricDiskMapping(u, v);

                float theta = elevation + discSamplePos.y * DegToRad(AppSettings::BaseSunSize);
                float gamma = discSamplePos.x * DegToRad(AppSettings::BaseSunSize);

                for(int32 i = 0; i < NumSpectralSamples; ++i)
                {
                    ArHosekSkyModelState* skyState = arhosekskymodelstate_alloc_init(elevation, turbidity, groundAlbedoSpectrum[i]);
                    float wavelength = Lerp(float(SampledLambdaStart), float(SampledLambdaEnd), i / float(NumSpectralSamples));

                    solarRadiance[i] = float(arhosekskymodel_solar_radiance(skyState, theta, gamma, wavelength));

                    arhosekskymodelstate_free(skyState);
                    skyState = nullptr;
                }

                Float3 sampleRadiance = solarRadiance.ToRGB();
                sunLuminance += sampleRadiance;
            }
        }

        // Account for luminous efficiency, coordinate system scaling, and sample averaging
        sunLuminance *= 683.0f * 100.0f * (1.0f / NumDiscSamples) * (1.0f / NumDiscSamples);

        sunLuminance = sunLuminance * tintColor;
        sunLuminance = sunLuminance * intensityScale;

        if(normalizeIntensity)
        {
            // Normalize so that the intensity stays the same even when the sun is bigger or smaller
            const float baseIntegral = IlluminanceIntegral(DegToRad(AppSettings::BaseSunSize));
            const float currIntegral = IlluminanceIntegral(DegToRad(AppSettings::SunSize));
            sunLuminance *= (baseIntegral / currIntegral);
        }

        turbidityCache = turbidity;
        sunDirectionCache = sunDirection;
        luminanceCache = sunLuminance;
        sunIntensityCache = intensityScale;
        sunTintCache = tintColor;
        normalizeCache = normalizeIntensity;
        sunSizeCache = sunSize;

        return sunLuminance;
    }