| 711 | } |
| 712 | |
| 713 | Float3 SunLuminance(bool& cached) |
| 714 | { |
| 715 | Float3 sunDirection = AppSettings::SunDirection; |
| 716 | sunDirection.y = Saturate(sunDirection.y); |
| 717 | sunDirection = Float3::Normalize(sunDirection); |
| 718 | const float turbidity = Clamp(AppSettings::Turbidity.Value(), 1.0f, 32.0f); |
| 719 | const float intensityScale = AppSettings::SunIntensityScale; |
| 720 | const Float3 tintColor = AppSettings::SunTintColor; |
| 721 | const bool32 normalizeIntensity = AppSettings::NormalizeSunIntensity; |
| 722 | const float sunSize = AppSettings::SunSize; |
| 723 | |
| 724 | static float turbidityCache = 2.0f; |
| 725 | static Float3 sunDirectionCache = Float3(-0.579149902f, 0.754439294f, -0.308879942f); |
| 726 | static Float3 luminanceCache = Float3(1.61212531e+009f, 1.36822630e+009f, 1.07235315e+009f) * FP16Scale; |
| 727 | static Float3 sunTintCache = Float3(1.0f, 1.0f, 1.0f); |
| 728 | static float sunIntensityCache = 1.0f; |
| 729 | static bool32 normalizeCache = false; |
| 730 | static float sunSizeCache = AppSettings::BaseSunSize; |
| 731 | |
| 732 | if(turbidityCache == turbidity && sunDirection == sunDirectionCache |
| 733 | && intensityScale == sunIntensityCache && tintColor == sunTintCache |
| 734 | && normalizeCache == normalizeIntensity && sunSize == sunSizeCache) |
| 735 | { |
| 736 | cached = true; |
| 737 | return luminanceCache; |
| 738 | } |
| 739 | |
| 740 | cached = false; |
| 741 | |
| 742 | float thetaS = std::acos(1.0f - sunDirection.y); |
| 743 | float elevation = Pi_2 - thetaS; |
| 744 | |
| 745 | // Get the sun's luminance, then apply tint and scale factors |
| 746 | Float3 sunLuminance; |
| 747 | |
| 748 | // For now, we'll compute an average luminance value from Hosek solar radiance model, even though |
| 749 | // we could compute illuminance directly while we're sampling the disk |
| 750 | SampledSpectrum groundAlbedoSpectrum = SampledSpectrum::FromRGB(GroundAlbedo); |
| 751 | SampledSpectrum solarRadiance; |
| 752 | |
| 753 | const uint64 NumDiscSamples = 8; |
| 754 | for(uint64 x = 0; x < NumDiscSamples; ++x) |
| 755 | { |
| 756 | for(uint64 y = 0; y < NumDiscSamples; ++y) |
| 757 | { |
| 758 | float u = (x + 0.5f) / NumDiscSamples; |
| 759 | float v = (y + 0.5f) / NumDiscSamples; |
| 760 | Float2 discSamplePos = SquareToConcentricDiskMapping(u, v); |
| 761 | |
| 762 | float theta = elevation + discSamplePos.y * DegToRad(AppSettings::BaseSunSize); |
| 763 | float gamma = discSamplePos.x * DegToRad(AppSettings::BaseSunSize); |
| 764 | |
| 765 | for(int32 i = 0; i < NumSpectralSamples; ++i) |
| 766 | { |
| 767 | ArHosekSkyModelState* skyState = arhosekskymodelstate_alloc_init(elevation, turbidity, groundAlbedoSpectrum[i]); |
| 768 | float wavelength = Lerp(float(SampledLambdaStart), float(SampledLambdaEnd), i / float(NumSpectralSamples)); |
| 769 | |
| 770 | solarRadiance[i] = float(arhosekskymodel_solar_radiance(skyState, theta, gamma, wavelength)); |
no test coverage detected