├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── atmosphere ├── atmosphere.cc ├── atmosphere.h ├── atmosphere_test.cc ├── color.cc ├── color.h ├── comparisons.cc ├── comparisons.h ├── hemispherical_function.h ├── hemispherical_function_test.cc ├── measurement │ ├── measured_atmosphere.cc │ ├── measured_atmosphere.h │ ├── measured_atmosphere_test.cc │ ├── measured_atmospheres.cc │ ├── measured_atmospheres.h │ └── testdata │ │ └── 2013-05-27___11.45.00 │ │ ├── 2013-05-27___11.45.00_-_0____0.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_10____112.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_11____123.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_12____135.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_13____146.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_14____157.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_15____168.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_16____180.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_17____191.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_18____202.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_19____213.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_1____11.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_20____225.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_21____236.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_22____247.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_23____258.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_24____270.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_25____281.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_26____292.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_27____303.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_28____315.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_29____326.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_2____22.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_30____337.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_31____348.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_32____345.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_33____330.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_34____315.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_35____300.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_36____285.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_37____270.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_38____255.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_39____240.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_3____33.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_40____225.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_41____210.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_42____195.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_43____180.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_44____165.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_45____150.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_46____135.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_47____120.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_48____105.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_49____90.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_4____45.0___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_50____75.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_51____60.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_52____45.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_53____30.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_54____15.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_55____0.0___33.749.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_56____0.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_57____22.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_58____45.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_59____67.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_5____56.25___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_60____90.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_61____112.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_62____135.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_63____157.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_64____180.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_65____202.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_66____225.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_67____247.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_68____270.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_69____292.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_6____67.5___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_70____315.0___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_71____337.5___53.3665.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_72____315.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_73____270.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_74____225.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_75____180.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_76____135.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_77____90.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_78____45.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_79____0.0___71.9187.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_7____78.75___12.1151.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_80____0.0___90.0.asd.rad.txt │ │ ├── 2013-05-27___11.45.00_-_8____90.0___12.1151.asd.rad.txt │ │ └── 2013-05-27___11.45.00_-_9____101.25___12.1151.asd.rad.txt ├── model │ ├── bruneton │ │ ├── bruneton.cc │ │ ├── bruneton.h │ │ ├── core.cc │ │ ├── core.h │ │ └── core.inl │ ├── haber │ │ ├── haber.cc │ │ └── haber.h │ ├── hosek │ │ ├── ArHosekSkyModel.cc │ │ ├── ArHosekSkyModel.h │ │ ├── ArHosekSkyModelData_CIEXYZ.h │ │ ├── ArHosekSkyModelData_RGB.h │ │ ├── ArHosekSkyModelData_Spectral.h │ │ ├── README.txt │ │ ├── hosek.cc │ │ └── hosek.h │ ├── libradtran │ │ ├── libradtran.cc │ │ └── libradtran.h │ ├── nishita │ │ ├── nishita93.cc │ │ ├── nishita93.h │ │ ├── nishita96.cc │ │ └── nishita96.h │ ├── oneal │ │ ├── oneal.cc │ │ └── oneal.h │ ├── polradtran │ │ ├── polradtran.cc │ │ └── polradtran.h │ └── preetham │ │ ├── preetham.cc │ │ └── preetham.h ├── sun_direction.cc └── sun_direction.h ├── clear_sky_models.cbp ├── input ├── 130527_130527_Egbert.pfn ├── astm-g173.txt └── kider_full_day_irradiance_raw_2013_5_27.txt ├── main.cc └── physics ├── cie.cc ├── cie.h ├── cie_test.cc └── units.h /.gitignore: -------------------------------------------------------------------------------- 1 | input/**/*.asd.txt 2 | input/**/*.asd.rad.txt 3 | output/** 4 | paper/figures/** 5 | main.plot 6 | paper.plot 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/dimensional_types"] 2 | path = external/dimensional_types 3 | url = https://github.com/ebruneton/dimensional_types 4 | [submodule "external/minpng"] 5 | path = external/minpng 6 | url = https://github.com/jrmuizel/minpng 7 | [submodule "external/progress_bar"] 8 | path = external/progress_bar 9 | url = https://github.com/ebruneton/progress_bar 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Eric Bruneton 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015 Eric Bruneton 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # 3. Neither the name of the copyright holder nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | GPP = g++ 30 | GPP_FLAGS = -Wall -Wmain -pedantic -pedantic-errors -std=c++11 31 | 32 | INCLUDE_FLAGS = -I. -Iexternal -Iexternal/dimensional_types -Iexternal/progress_bar 33 | 34 | DEBUG_FLAGS = -g 35 | RELEASE_FLAGS = -DNDEBUG -O3 -fexpensive-optimizations 36 | 37 | DIRS := atmosphere physics 38 | 39 | HEADERS := $(shell find $(DIRS) -name "*.h") 40 | SOURCES := $(shell find $(DIRS) -name "*.cc" \ 41 | -not -name "*test*" -not -name "main.cc") 42 | TEST_SOURCES := $(shell find $(DIRS) -name "*test*.cc") 43 | ALL_SOURCES := $(HEADERS) $(SOURCES) $(TEST_SOURCES) main.cc 44 | LINT_SOURCES := $(filter-out atmosphere/model/hosek/ArHosek%,$(ALL_SOURCES)) 45 | 46 | DEBUG_OBJECTS := $(SOURCES:%.cc=output/Debug/%.o) \ 47 | output/Debug/external/progress_bar/util/progress_bar.o 48 | 49 | RELEASE_OBJECTS := $(SOURCES:%.cc=output/Release/%.o) \ 50 | output/Release/external/progress_bar/util/progress_bar.o 51 | 52 | TEST_OBJECTS := $(TEST_SOURCES:%.cc=output/Debug/%.o) \ 53 | output/Debug/external/progress_bar/util/progress_bar.o \ 54 | output/Debug/external/dimensional_types/test/test_main.o 55 | 56 | ARCHIVE_URL := \ 57 | http://web.archive.org/web/20160617214029/http://www.graphics.cornell.edu/resources/clearsky/data/2013-05-27/RADIANCE/ 58 | ARCHIVES := \ 59 | 2013-05-27___09.30.00.7z 2013-05-27___09.45.00.7z \ 60 | 2013-05-27___10.00.00.7z 2013-05-27___10.15.00.7z \ 61 | 2013-05-27___10.30.00.7z 2013-05-27___10.45.00.7z \ 62 | 2013-05-27___11.00.00.7z 2013-05-27___11.15.00.7z \ 63 | 2013-05-27___11.30.00.7z 2013-05-27___11.45.00.7z \ 64 | 2013-05-27___12.00.00.7z 2013-05-27___12.15.00.7z \ 65 | 2013-05-27___12.30.00.7z 2013-05-27___12.45.00.7z \ 66 | 2013-05-27___13.00.00.7z 2013-05-27___13.15.00.7z \ 67 | 2013-05-27___13.30.00.7z 68 | 69 | INPUTS := $(ARCHIVES:%.7z=input/%) 70 | 71 | input/%: 72 | wget -O input/$*.7z $(ARCHIVE_URL)/$*.7z 73 | 7zr x -oinput input/$*.7z 74 | rm input/$*.7z 75 | 76 | output/Debug/%.o: %.cc 77 | mkdir -p $(@D) 78 | $(GPP) $(GPP_FLAGS) $(DEBUG_FLAGS) $(INCLUDE_FLAGS) -c $< -o $@ 79 | 80 | output/Release/%.o: %.cc 81 | mkdir -p $(@D) 82 | $(GPP) $(GPP_FLAGS) $(RELEASE_FLAGS) $(INCLUDE_FLAGS) -c $< -o $@ 83 | 84 | output/Debug/clearskymodels: $(DEBUG_OBJECTS) output/Debug/main.o 85 | mkdir -p $(@D) 86 | $(GPP) -pthread -s -o $@ $^ 87 | 88 | output/Release/clearskymodels: $(RELEASE_OBJECTS) output/Release/main.o 89 | mkdir -p $(@D) 90 | $(GPP) -pthread -s -o $@ $^ 91 | 92 | output/Debug/clearskymodels_test: $(DEBUG_OBJECTS) $(TEST_OBJECTS) 93 | mkdir -p $(@D) 94 | $(GPP) -pthread -s -o $@ $^ 95 | 96 | # cpplint can be installed with "pip install cpplint". 97 | lint: $(LINT_SOURCES) 98 | cpplint --root=$(PWD) $^ 99 | 100 | all: output/Debug/clearskymodels output/Release/clearskymodels $(INPUTS) 101 | mkdir -p output/cache/bruneton 102 | mkdir -p output/cache/haber 103 | mkdir -p output/cache/input 104 | mkdir -p output/cache/nishita 105 | mkdir -p output/cache/polradtran 106 | mkdir -p output/figures 107 | mkdir -p output/libradtran 108 | output/Release/clearskymodels \ 109 | /usr/local/bin/uvspec /usr/local/share/libRadtran/data 110 | 111 | test: output/Debug/clearskymodels_test 112 | output/Debug/clearskymodels_test 113 | 114 | clean: 115 | rm -rf output/Debug 116 | rm -rf output/Release 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Synopsis 2 | 3 | This project implements 8 clear sky models in a common framework to compare 4 | them with each other and with a reference model and reference measurements. 5 | 6 | ## License 7 | 8 | This project is released under the BSD license. 9 | -------------------------------------------------------------------------------- /atmosphere/atmosphere.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/atmosphere.h" 31 | 32 | #include 33 | 34 | namespace { 35 | 36 | IrradianceSpectrum NewSolarSpectrum() { 37 | // Values from "Reference Solar Spectral Irradiance: ASTM G-173", ETR column 38 | // (see http://rredc.nrel.gov/solar/spectra/am1.5/ASTMG173/ASTMG173.html), 39 | // summed and averaged in each bin (e.g. the value for 360nm is the average of 40 | // the ASTM G-173 values for all wavelengths between 360 and 371.75nm). 41 | static const float kSpectralIrradiance[40] = { 42 | 1.13419, 1.09801, 1.03541, 1.45086, 1.72453, 1.654, 1.70536, 1.97393, 43 | 2.03543, 2.00643, 1.95531, 1.95426, 1.92438, 1.82092, 1.88517, 1.85545, 44 | 1.85083, 1.82758, 1.84475, 1.78771, 1.76683, 1.70858, 1.68278, 1.63849, 45 | 1.59608, 1.52211, 1.52468, 1.47836, 1.4485, 1.40522, 1.35526, 1.32788, 46 | 1.28834, 1.26938, 1.23241, 1.20345, 1.17087, 1.1344, 1.11012, 1.07147 47 | }; 48 | IrradianceSpectrum result; 49 | for (unsigned int i = 0; i < result.size(); ++i) { 50 | result[i] = kSpectralIrradiance[i] * watt_per_square_meter_per_nm; 51 | } 52 | return result; 53 | } 54 | 55 | ScatteringSpectrum NewRayleighScattering() { 56 | // Values from Table III in Penndorf 1957 "Tables of the Refractive Index for 57 | // Standard Air and the Rayleigh Scattering Coefficient for the Spectral 58 | // Region between 0.2 and 20.0 μ and Their Application to Atmospheric Optics". 59 | static const float kPenndorf[48] = { 60 | 70.45E-6, 62.82E-6, 56.20E-6, 50.43E-6, 45.40E-6, 40.98E-6, 37.08E-6, 61 | 33.65E-6, 30.60E-6, 27.89E-6, 25.48E-6, 23.33E-6, 21.40E-6, 19.66E-6, 62 | 18.10E-6, 16.69E-6, 15.42E-6, 14.26E-6, 13.21E-6, 12.26E-6, 11.39E-6, 63 | 10.60E-6, 9.876E-6, 9.212E-6, 8.604E-6, 8.045E-6, 7.531E-6, 7.057E-6, 64 | 6.620E-6, 6.217E-6, 5.844E-6, 5.498E-6, 5.178E-6, 4.881E-6, 4.605E-6, 65 | 4.348E-6, 4.109E-6, 3.886E-6, 3.678E-6, 3.484E-6, 3.302E-6, 3.132E-6, 66 | 2.973E-6, 2.824E-6, 2.684E-6, 2.583E-6, 2.481E-6, 2.380E-6 67 | }; 68 | std::vector penndorf_samples; 69 | for (int i = 0; i < 48; ++i) { 70 | // The above values are for T_0=0°C. For T=15°C, a correction factor 71 | // T_0 / T must be applied (Eq. (12) in Penndorf paper). 72 | constexpr double T_0 = 273.16; 73 | constexpr double T = T_0 + 15.0; 74 | penndorf_samples.push_back(kPenndorf[i] * (T_0 / T) / m); 75 | } 76 | return ScatteringSpectrum(360.0 * nm, 830.0 * nm, penndorf_samples); 77 | } 78 | 79 | ScatteringSpectrum NewMieExtinction(double angstrom_alpha, 80 | double angstrom_beta) { 81 | ScatteringSpectrum mie; 82 | for (unsigned int i = 0; i < mie.size(); ++i) { 83 | double lambda = mie.GetSample(i).to(1000.0 * nm); 84 | mie[i] = angstrom_beta * pow(lambda, -angstrom_alpha) / MieScaleHeight; 85 | } 86 | return mie; 87 | } 88 | 89 | ScatteringSpectrum NewMieScattering(double angstrom_alpha, 90 | double angstrom_beta) { 91 | const double kSingleScatteringAlbedo = 0.8; 92 | return 93 | NewMieExtinction(angstrom_alpha, angstrom_beta) * kSingleScatteringAlbedo; 94 | } 95 | 96 | DimensionlessSpectrum NewGroundAlbedo() { 97 | // Grass spectral albedo from Uwe Feister and Rolf Grewe, "Spectral albedo 98 | // measurements in the UV and visible region over different types of 99 | // surfaces", Photochemistry and Photobiology, 62, 736-744, 1995. 100 | static const float kGrassAlbedo[45] = { 101 | 0.018, 0.019, 0.019, 0.020, 0.022, 0.024, 0.027, 0.029, 0.030, 0.031, 0.032, 102 | 0.032, 0.032, 0.033, 0.035, 0.040, 0.055, 0.073, 0.084, 0.089, 0.089, 0.079, 103 | 0.069, 0.063, 0.061, 0.057, 0.052, 0.051, 0.048, 0.042, 0.039, 0.035, 0.035, 104 | 0.043, 0.087, 0.156, 0.234, 0.334, 0.437, 0.513, 0.553, 0.571, 0.579, 0.581, 105 | 0.587 106 | }; 107 | std::vector grass_albedo_samples; 108 | for (int i = 0; i < 45; ++i) { 109 | grass_albedo_samples.push_back(kGrassAlbedo[i]); 110 | } 111 | return DimensionlessSpectrum(360.0 * nm, 800.0 * nm, grass_albedo_samples); 112 | } 113 | 114 | const IrradianceSpectrum solar_spectrum = NewSolarSpectrum(); 115 | const ScatteringSpectrum rayleigh_scattering = NewRayleighScattering(); 116 | const ScatteringSpectrum mie_extinction = 117 | NewMieExtinction(MieAngstromAlpha, MieAngstromBeta); 118 | const ScatteringSpectrum mie_scattering = 119 | NewMieScattering(MieAngstromAlpha, MieAngstromBeta); 120 | const DimensionlessSpectrum ground_albedo = NewGroundAlbedo(); 121 | 122 | } // anonymous namespace 123 | 124 | const IrradianceSpectrum& SolarSpectrum() { return solar_spectrum; } 125 | const ScatteringSpectrum& RayleighScattering() { return rayleigh_scattering; } 126 | const ScatteringSpectrum& MieExtinction() { return mie_extinction; } 127 | const ScatteringSpectrum& MieScattering() { return mie_scattering; } 128 | 129 | ScatteringSpectrum MieExtinction(double angstrom_alpha, double angstrom_beta) { 130 | return NewMieExtinction(angstrom_alpha, angstrom_beta); 131 | } 132 | 133 | ScatteringSpectrum MieScattering(double angstrom_alpha, double angstrom_beta) { 134 | return NewMieScattering(angstrom_alpha, angstrom_beta); 135 | } 136 | 137 | InverseSolidAngle RayleighPhaseFunction(Angle scattering_angle) { 138 | return RayleighPhaseFunction(cos(scattering_angle)); 139 | } 140 | 141 | InverseSolidAngle RayleighPhaseFunction(Number scattering_angle_cosine) { 142 | constexpr InverseSolidAngle kRayleigh = 143 | 3.0 / (16.0 * PI) * InverseSolidAngle::Unit(); 144 | return kRayleigh * (1.0 + scattering_angle_cosine * scattering_angle_cosine); 145 | } 146 | 147 | InverseSolidAngle MiePhaseFunction(Angle scattering_angle) { 148 | return MiePhaseFunction(cos(scattering_angle)); 149 | } 150 | 151 | InverseSolidAngle MiePhaseFunction(Number scattering_angle_cosine) { 152 | constexpr double g = MiePhaseFunctionG; 153 | constexpr InverseSolidAngle kMie = 3.0 / (8.0 * PI) * 154 | (1.0 - g * g) / (2.0 + g * g) * InverseSolidAngle::Unit(); 155 | return kMie * (1.0 + scattering_angle_cosine * scattering_angle_cosine) / 156 | pow(1.0 + g * g - 2.0 * g * scattering_angle_cosine, 1.5); 157 | } 158 | 159 | InverseSolidAngle MiePhaseFunction(double g, Number scattering_angle_cosine) { 160 | const InverseSolidAngle kMie = 3.0 / (8.0 * PI) * 161 | (1.0 - g * g) / (2.0 + g * g) * InverseSolidAngle::Unit(); 162 | return kMie * (1.0 + scattering_angle_cosine * scattering_angle_cosine) / 163 | pow(1.0 + g * g - 2.0 * g * scattering_angle_cosine, 1.5); 164 | } 165 | 166 | const DimensionlessSpectrum& GroundAlbedo() { return ground_albedo; } 167 | 168 | int Atmosphere::GetOriginalNumberOfWavelengths() const { 169 | return DimensionlessSpectrum::SIZE; 170 | } 171 | 172 | IrradianceSpectrum Atmosphere::GetSkyIrradiance(Length altitude, 173 | Angle sun_zenith) const { 174 | IrradianceSpectrum result = 175 | IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm); 176 | const unsigned int N = 100; 177 | for (unsigned int i = 0; i < N / 2; ++i) { 178 | Angle view_zenith = (i + 0.5) * pi / N; 179 | Number cos_view_zenith = cos(view_zenith); 180 | Number sin_view_zenith = sin(view_zenith); 181 | for (unsigned int j = 0; j < 2 * N; ++j) { 182 | Angle view_azimuth = j * pi / N; 183 | RadianceSpectrum incident_spectrum = 184 | GetSkyRadiance(altitude, sun_zenith, view_zenith, view_azimuth); 185 | SolidAngle domega = sin_view_zenith * (PI / N) * (PI / N) * sr; 186 | result = result + incident_spectrum * cos_view_zenith * domega; 187 | } 188 | } 189 | return result; 190 | } 191 | 192 | RadianceSpectrum Atmosphere::GetSkyRadiance(Length altitude, Angle sun_zenith, 193 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const { 194 | return GetSkyRadiance( 195 | altitude, sun_zenith, view_zenith, view_azimuth - sun_azimuth); 196 | } 197 | 198 | Angle Atmosphere::GetViewSunAngle(Angle sun_zenith, Angle view_zenith, 199 | Angle view_sun_azimuth) { 200 | return acos(cos(view_sun_azimuth) * sin(view_zenith) * sin(sun_zenith) + 201 | cos(view_zenith) * cos(sun_zenith)); 202 | } 203 | -------------------------------------------------------------------------------- /atmosphere/atmosphere.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_ATMOSPHERE_H_ 31 | #define ATMOSPHERE_ATMOSPHERE_H_ 32 | 33 | #include "math/angle.h" 34 | #include "physics/units.h" 35 | 36 | constexpr Length EarthRadius = 6360.0 * km; 37 | constexpr Length AtmosphereRadius = 6420.0 * km; 38 | 39 | // The height of the atmosphere if its density was uniform. 40 | constexpr Length RayleighScaleHeight = 8000.0 * m; 41 | 42 | // The height of the Mie particle layer if its density was uniform. 43 | constexpr Length MieScaleHeight = 1200.0 * m; 44 | 45 | // The Angstrom alpha coefficient for the Mie optical depth. 46 | constexpr double MieAngstromAlpha = 0.8; 47 | 48 | // The Angstrom beta coefficient for the Mie optical depth. 49 | constexpr double MieAngstromBeta = 0.04; 50 | 51 | // The g parameter of the Cornette-Shanks phase function used for Mie particles. 52 | constexpr double MiePhaseFunctionG = 0.7; 53 | 54 | // The Linke turbidity value, for the Preetham and Hosek models. 55 | constexpr double Turbidity = 2.53; 56 | 57 | // Returns the spectral irradiance of the Sun at the top of the atmosphere. 58 | const IrradianceSpectrum& SolarSpectrum(); 59 | 60 | // Returns the Rayleigh scattering coefficient at sea level. 61 | const ScatteringSpectrum& RayleighScattering(); 62 | 63 | // Returns the Mie extinction coefficient at sea level. 64 | const ScatteringSpectrum& MieExtinction(); 65 | 66 | // Returns the Mie scattering coefficient at sea level. 67 | const ScatteringSpectrum& MieScattering(); 68 | 69 | // Returns the Mie extinction and scattering coefficients at sea level for 70 | // the given Angstrom parameters. 71 | ScatteringSpectrum MieExtinction(double angstrom_alpha, double angstrom_beta); 72 | ScatteringSpectrum MieScattering(double angstrom_alpha, double angstrom_beta); 73 | 74 | // Computes the Rayleigh phase function for the given scattering angle. 75 | // The integral of this function over all solid angles is 1. 76 | InverseSolidAngle RayleighPhaseFunction(Angle scattering_angle); 77 | InverseSolidAngle RayleighPhaseFunction(Number scattering_angle_cosine); 78 | 79 | // Computes the Mie phase function for the given scattering angle (using 80 | // the Cornette-Shanks approximation). 81 | // The integral of this function over all solid angles is 1. 82 | InverseSolidAngle MiePhaseFunction(Angle scattering_angle); 83 | InverseSolidAngle MiePhaseFunction(Number scattering_angle_cosine); 84 | InverseSolidAngle MiePhaseFunction(double g, Number scattering_angle_cosine); 85 | 86 | const DimensionlessSpectrum& GroundAlbedo(); 87 | 88 | // An abstract atmosphere model. 89 | class Atmosphere { 90 | public: 91 | virtual ~Atmosphere() {} 92 | 93 | // Returns the number of wavelengths originally used by this atmosphere model. 94 | // The default implementation returns spectrum::NUM_WAVELENGTH. 95 | virtual int GetOriginalNumberOfWavelengths() const; 96 | 97 | // Returns the irradiance on a plane perpendicular to the Sun direction. 98 | virtual IrradianceSpectrum GetSunIrradiance(Length altitude, 99 | Angle sun_zenith) const = 0; 100 | 101 | virtual RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 102 | Angle view_zenith, Angle view_sun_azimuth) const = 0; 103 | 104 | virtual RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 105 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 106 | 107 | // Returns the irradiance on a horizontal plane. 108 | virtual IrradianceSpectrum GetSkyIrradiance(Length altitude, 109 | Angle sun_zenith) const; 110 | 111 | protected: 112 | static Angle GetViewSunAngle(Angle sun_zenith, Angle view_zenith, 113 | Angle view_sun_azimuth); 114 | }; 115 | 116 | #endif // ATMOSPHERE_ATMOSPHERE_H_ 117 | -------------------------------------------------------------------------------- /atmosphere/atmosphere_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/atmosphere.h" 31 | 32 | #include 33 | 34 | #include "test/test_case.h" 35 | 36 | class UniformSky : public Atmosphere { 37 | public: 38 | IrradianceSpectrum GetSunIrradiance(Length altitude, 39 | Angle sun_zenith) const { 40 | return IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm); 41 | } 42 | 43 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 44 | Angle view_zenith, Angle view_sun) const { 45 | return RadianceSpectrum(1.0 * watt_per_square_meter_per_sr_per_nm); 46 | } 47 | }; 48 | 49 | class TestAtmosphere : public dimensional::TestCase { 50 | public: 51 | template 52 | TestAtmosphere(const std::string& name, T test) 53 | : TestCase("TestAtmosphere " + name, static_cast(test)) {} 54 | 55 | void TestSolarSpectrum() { 56 | ExpectNear(734.0, Integral(SolarSpectrum()).to(watt_per_square_meter), 1.0); 57 | } 58 | 59 | void TestPhaseFunctions() { 60 | // Check that the phase functions integrated over 4.pi sr give 1. 61 | Number rayleigh_integral = 0.0; 62 | Number mie_integral = 0.0; 63 | const unsigned int N = 100; 64 | for (unsigned int i = 0; i < N; ++i) { 65 | Angle theta = (i + 0.5) * pi / N; 66 | SolidAngle domega = sin(theta) * (PI / N) * (2.0 * PI) * sr; 67 | rayleigh_integral = 68 | rayleigh_integral + RayleighPhaseFunction(theta) * domega; 69 | mie_integral = 70 | mie_integral + MiePhaseFunction(theta) * domega; 71 | } 72 | ExpectNear(1.0, rayleigh_integral(), 1e-3); 73 | ExpectNear(1.0, mie_integral(), 1e-3); 74 | } 75 | 76 | void TestSkyIrradiance() { 77 | // Check that the irradiance of a sky with uniform radiance 1 is pi. 78 | UniformSky sky; 79 | IrradianceSpectrum spectrum = sky.GetSkyIrradiance(0.0 * m, 0.0 * rad); 80 | for (unsigned int i = 0; i < spectrum.size(); ++i) { 81 | ExpectNear(PI, spectrum[i].to(watt_per_square_meter_per_nm), 1e-3); 82 | } 83 | } 84 | }; 85 | 86 | namespace { 87 | 88 | TestAtmosphere solarspectrum( 89 | "solarspectrum", &TestAtmosphere::TestSolarSpectrum); 90 | TestAtmosphere phasefunctions( 91 | "phasefunctions", &TestAtmosphere::TestPhaseFunctions); 92 | TestAtmosphere skyirradiance( 93 | "skyirradiance", &TestAtmosphere::TestSkyIrradiance); 94 | 95 | } // anonymous namespace 96 | -------------------------------------------------------------------------------- /atmosphere/color.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/color.h" 31 | 32 | #include "atmosphere/atmosphere.h" 33 | #include "math/matrix.h" 34 | 35 | using dimensional::Matrix3; 36 | using dimensional::Vector3; 37 | using dimensional::Scalar; 38 | using dimensional::vec3; 39 | 40 | namespace { 41 | 42 | // The 3 sample wavelengths used when simulating RGB rendering. All the models 43 | // are run spectrally, but we can simulate RGB rendering by simply dropping the 44 | // values at all wavelengths but 3. 45 | constexpr Wavelength lambda_r = 680.0 * nm; 46 | constexpr Wavelength lambda_g = 550.0 * nm; 47 | constexpr Wavelength lambda_b = 440.0 * nm; 48 | 49 | } // namespace 50 | 51 | Color GetSrgbColorNaive(const RadianceSpectrum& spectrum) { 52 | // Extract 3 samples of the given spectrum, to be used as RGB components. Note 53 | // that 'spectrum' is proportional to the input solar spectrum, whereas the 54 | // original O'Neal and Bruneton model implementations implicitly use a 55 | // wavelength independent solar spectrum. To simulate this, we need to cancel 56 | // the effect of the input solar spectrum when extracting the RGB values: 57 | static const RadianceSpectrum solar_spectrum = SolarSpectrum() * (1.0 / sr); 58 | Number r = spectrum(lambda_r) / solar_spectrum(lambda_r); 59 | Number g = spectrum(lambda_g) / solar_spectrum(lambda_g); 60 | Number b = spectrum(lambda_b) / solar_spectrum(lambda_b); 61 | // Scale the resulting color with a constant factor such that the result can 62 | // be compared quantitatively with the correct way of converting 'spectrum' to 63 | // a color, as in GetSrgbColor(). 64 | static const auto k = 65 | dot(GetSrgbColor(solar_spectrum), vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); 66 | return Color(k * r, k * g, k * b); 67 | } 68 | 69 | Color GetSrgbColorFrom3SpectrumSamples(const RadianceSpectrum& spectrum) { 70 | // Compute the normalization vector to properly convert 3 spectrum samples to 71 | // a perceptual, linear sRGB color. 72 | static const auto k = []() { 73 | WavelengthFunction<0, -3, 0, 0, 0> f; 74 | for (unsigned int i = 0; i < f.size(); ++i) { 75 | Wavelength lambda = f.GetSample(i); 76 | f[i] = 1.0 / (lambda * lambda * lambda); 77 | } 78 | const auto RGB = XYZ_to_sRGB * Vector3>( 79 | Integral(cie_x_bar_function() * SolarSpectrum() * f), 80 | Integral(cie_y_bar_function() * SolarSpectrum() * f), 81 | Integral(cie_z_bar_function() * SolarSpectrum() * f)) * 82 | MaxLuminousEfficacy; 83 | return Vector3>( 84 | RGB.x / SolarSpectrum()(lambda_r) * (lambda_r * lambda_r * lambda_r), 85 | RGB.y / SolarSpectrum()(lambda_g) * (lambda_g * lambda_g * lambda_g), 86 | RGB.z / SolarSpectrum()(lambda_b) * (lambda_b * lambda_b * lambda_b)); 87 | }(); 88 | return Color(k.x * spectrum(lambda_r), k.y * spectrum(lambda_g), 89 | k.z * spectrum(lambda_b)); 90 | } 91 | 92 | // Returns an approximate version of the given spectrum, reconstructed from 3 of 93 | // its samples with the CIE S0, S1 and S2 components. 94 | RadianceSpectrum GetApproximateSpectrumFrom3SpectrumSamples( 95 | const RadianceSpectrum& spectrum) { 96 | static const Matrix3 sRGB_to_XYZ = inverse(XYZ_to_sRGB); 97 | Color XYZ = sRGB_to_XYZ * GetSrgbColorFrom3SpectrumSamples(spectrum); 98 | Number x = XYZ.x / (XYZ.x + XYZ.y + XYZ.z); 99 | Number y = XYZ.y / (XYZ.x + XYZ.y + XYZ.z); 100 | Radiance Y = XYZ.y / MaxLuminousEfficacy; 101 | Number M1 = (-1.3515 - 1.7703 * x + 5.9114 * y) / 102 | (0.0241 + 0.2562 * x - 0.7341 * y); 103 | Number M2 = (0.0300 - 31.4424 * x + 30.0717 * y) / 104 | (0.0241 + 0.2562 * x - 0.7341 * y); 105 | DimensionlessSpectrum S = 106 | S0_function() + S1_function() * M1 + S2_function() * M2; 107 | static const auto Y_S0 = Integral(S0_function() * cie_y_bar_function()); 108 | static const auto Y_S1 = Integral(S1_function() * cie_y_bar_function()); 109 | static const auto Y_S2 = Integral(S2_function() * cie_y_bar_function()); 110 | SpectralRadiance k = Y / (Y_S0 + Y_S1 * M1 + Y_S2 * M2); 111 | return S * k; 112 | } 113 | 114 | Color WhiteBalanceNaive(const Color& c) { 115 | const Color sun_color = GetSrgbColor(SolarSpectrum() * (1.0 / sr)); 116 | const Luminance sun_luminance = 117 | dot(sun_color, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); 118 | const auto white_point = sun_color / sun_luminance; 119 | return Color(c.x / white_point.x, c.y / white_point.y, c.z / white_point.z); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /atmosphere/color.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_COLOR_H_ 31 | #define ATMOSPHERE_COLOR_H_ 32 | 33 | #include "physics/cie.h" 34 | #include "physics/units.h" 35 | 36 | // Converts the given spectrum to a RGB color using the "naive", and incorrect, 37 | // method from the Nishita93, Nishita96, O'Neal and Bruneton models, i.e. by 38 | // simply using the spectrum value at 3 wavelengths for red, green and blue (and 39 | // assuming a wavelength independent solar spectrum). This bypasses the CIE 40 | // color matching functions, which are needed to correctly convert spectral 41 | // quantities to perceptual quantities. 42 | Color GetSrgbColorNaive(const RadianceSpectrum& spectrum); 43 | 44 | // Extracts 3 values from the given spectrum, and convert them "correctly" to an 45 | // sRGB color, as if the whole spectrum was converted with GetSrgbColor. This 46 | // method is based on an approximate reconstruction of the given spectrum around 47 | // each of the 3 extracted values, using our knowledge that this spectrum is 48 | // proportional to the solar spectrum and approximately proportional to 49 | // lambda^(-alpha), with alpha < 4 due to aerosols. In the end, the conversion 50 | // from the 3 samples to an sRGB color is done with a simple constant, 51 | // precomputed 3 vector. 52 | Color GetSrgbColorFrom3SpectrumSamples(const RadianceSpectrum& spectrum); 53 | 54 | // Returns an approximate version of the given spectrum, reconstructed from 3 of 55 | // its samples with the CIE S0, S1 and S2 components. The 3 samples are first 56 | // converted to sRGB with GetSrgbColorFrom3SpectrumSamples(), then to XYZ and 57 | // xyY, and finally to a full spectrum using the CIE S0, S1 and S2 components. 58 | RadianceSpectrum GetApproximateSpectrumFrom3SpectrumSamples( 59 | const RadianceSpectrum& spectrum); 60 | 61 | // Performs a "naive" white balance, by dividing the given color by the 62 | // (normalized) sun color. 63 | Color WhiteBalanceNaive(const Color& c); 64 | 65 | #endif // ATMOSPHERE_COLOR_H_ 66 | -------------------------------------------------------------------------------- /atmosphere/comparisons.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_COMPARISONS_H_ 31 | #define ATMOSPHERE_COMPARISONS_H_ 32 | 33 | #include 34 | #include 35 | 36 | #include "atmosphere/atmosphere.h" 37 | #include "atmosphere/color.h" 38 | #include "atmosphere/hemispherical_function.h" 39 | #include "atmosphere/measurement/measured_atmospheres.h" 40 | #include "math/angle.h" 41 | #include "physics/units.h" 42 | 43 | class Comparisons { 44 | public: 45 | Comparisons(const std::string& name, const Atmosphere& atmosphere, 46 | const MeasuredAtmospheres& reference, Wavelength min_wavelength, 47 | Wavelength max_wavelength); 48 | 49 | const std::string& name() const { return name_; } 50 | 51 | void RenderSkyImage(const std::string& name, Angle sun_zenith, 52 | Angle sun_azimuth, bool white_balance) const; 53 | 54 | void PlotSunIlluminanceAttenuation() const; 55 | 56 | void PlotRadiance(const std::string& name, Angle sun_zenith, 57 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 58 | 59 | void RenderLuminanceAndImage(const std::string& name, Angle sun_zenith, 60 | Angle sun_azimuth) const; 61 | 62 | void PlotLuminanceProfile(const std::string& name, Angle sun_zenith, 63 | Angle sun_azimuth) const; 64 | 65 | SpectralRadiance PlotRelativeError(const std::string& name, 66 | Angle sun_zenith, Angle sun_azimuth, 67 | SpectralRadiance* rmse_with_approximate_spectrum) const; 68 | 69 | void PlotRelativeError(const std::string& name, const Atmosphere& reference, 70 | Angle sun_zenith, Angle sun_azimuth) const; 71 | 72 | SpectralRadiance ComputeTotalRmse(const std::vector& sun_zenith, 73 | const std::vector& sun_azimuth) const; 74 | 75 | Luminance ComputeZenithLuminance(Angle sun_zenith) const; 76 | void ComputeIrradiance(Angle sun_zenith, Irradiance* sun, 77 | Irradiance* sky) const; 78 | 79 | void PlotDayZenithLuminance(const std::vector& sun_zenith, 80 | const std::vector& zenith_luminance) const; 81 | void PlotDayIrradiance(const std::vector& sun_zenith, 82 | const std::vector& sun, 83 | const std::vector& sky) const; 84 | 85 | static const std::string GetOutputDir(); 86 | static std::string SaveGroundAlbedo(); 87 | static std::string SaveErrorCaption(); 88 | static std::string SaveScaleCaption(); 89 | 90 | private: 91 | std::string name_; 92 | const Atmosphere& atmosphere_; 93 | const MeasuredAtmospheres& reference_; 94 | Wavelength min_wavelength_; 95 | Wavelength max_wavelength_; 96 | 97 | Color GetOriginalColor(const RadianceSpectrum& radiance) const; 98 | 99 | SpectralRadiance ComputeRelativeErrorAndRmse(Angle sun_zenith, 100 | Angle sun_azimuth, HemisphericalFunction* relative_error, 101 | SpectralRadiance* rmse_with_approximate_spectrum, Number* rgb_rmse, 102 | Number* original_rgb_rmse, Number* approximate_rgb_rmse) const; 103 | }; 104 | 105 | #endif // ATMOSPHERE_COMPARISONS_H_ 106 | -------------------------------------------------------------------------------- /atmosphere/hemispherical_function.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_HEMISPHERICAL_FUNCTION_H_ 31 | #define ATMOSPHERE_HEMISPHERICAL_FUNCTION_H_ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "physics/units.h" 41 | 42 | // A function from the hemisphere to values of type T represented by its values 43 | // at 9x9 sample points mapped from the unit square to the hemisphere (using 44 | // "A low distortion map between disk and square.", Hirley et al. 1997), and 45 | // interpolated with bicubic interpolation in between. 46 | template 47 | class HemisphericalFunction { 48 | public: 49 | inline const T& Get(int i, int j) const { 50 | assert(i >= 0 && i < 9 && j >= 0 && j < 9); 51 | return value_[i][j]; 52 | } 53 | 54 | inline T& Get(int i, int j) { 55 | assert(i >= 0 && i < 9 && j >= 0 && j < 9); 56 | return value_[i][j]; 57 | } 58 | 59 | inline void Set(int i, int j, const T& value) { 60 | assert(i >= 0 && i < 9 && j >= 0 && j < 9); 61 | value_[i][j] = value; 62 | } 63 | 64 | static void GetSampleDirection(int i, int j, Angle* view_zenith, 65 | Angle* view_azimuth) { 66 | double r; 67 | double phi; 68 | ToUnitDisk((i + 0.5) / 9, (j + 0.5) / 9, &r, &phi); 69 | *view_zenith = acos(1.0 - r * r) * rad; 70 | *view_azimuth = phi * rad; 71 | } 72 | 73 | T operator()(Angle view_zenith, Angle view_azimuth) const { 74 | // Computes the nearest ring indices corresponding to view_zenith and 75 | // returns the cubic interpolation of the function values on these rings 76 | // (themselves interpolated from the sample values using cubic 77 | // interpolation, see below). 78 | Number z = cos(view_zenith); 79 | double r = std::sqrt(1.0 - z()); 80 | double u = 4.5 * r; 81 | int i = std::floor(u); 82 | u -= i; 83 | return Cubic(u, GetRing(i - 1, view_azimuth), GetRing(i, view_azimuth), 84 | GetRing(i + 1, view_azimuth), GetRing(i + 2, view_azimuth)); 85 | } 86 | 87 | void Load(const std::string& filename) { 88 | std::ifstream file(filename, std::ifstream::binary | std::ifstream::in); 89 | for (int i = 0; i < 9; ++i) { 90 | file.read(reinterpret_cast(&(value_[i])), 9 * sizeof(T)); 91 | } 92 | file.close(); 93 | } 94 | 95 | void Save(const std::string& filename) const { 96 | std::ofstream file(filename, std::ofstream::binary); 97 | for (int i = 0; i < 9; ++i) { 98 | file.write(reinterpret_cast(&(value_[i])), 9 * sizeof(T)); 99 | } 100 | file.close(); 101 | } 102 | 103 | private: 104 | // From "A low distortion map between disk and square.", Hirley et al. 1997. 105 | static void ToUnitDisk(double x, double y, double *r, double *phi) { 106 | double a = 2 * x - 1; 107 | double b = 2 * y - 1; 108 | if (a > -b) { 109 | if (a > b) { 110 | *r = a; 111 | *phi = (dimensional::PI / 4) * (b / a); 112 | } else { 113 | *r = b; 114 | *phi = (dimensional::PI / 4) * (2 - (a / b)); 115 | } 116 | } else { 117 | if (a < b) { 118 | *r = -a; 119 | *phi = (dimensional::PI / 4) * (4 + (b / a)); 120 | } else { 121 | *r = -b; 122 | if (b != 0.0) { 123 | *phi = (dimensional::PI / 4) * (6 - (a / b)); 124 | } else { 125 | *phi = 0; 126 | } 127 | } 128 | } 129 | } 130 | 131 | // Returns the interpolated value of the hemispherical function on the given 132 | // ring (see GetRing below), using cubic interpolation of the nearest samples 133 | // on this ring. Also extrapolate the results to ring index -1 such that the 134 | // interpolated function is differentiable at the zenith, and to ring indices 135 | // larger than 4 to extrapolate the function up to the horizon. 136 | T GetRing(int ring_index, Angle view_azimuth) const { 137 | assert(ring_index >= -1); 138 | if (ring_index == -1) { 139 | // Computes the value such that the finite difference derivative 140 | // 0.5 * (GetRing(1, view_azimuth) - GetRing(-1, view_azimuth)) 141 | // is equal to GetZenithDerivative(view_azimuth). 142 | return GetRing(1, view_azimuth) - GetZenithDerivative(view_azimuth) * 2.0; 143 | } else if (ring_index > 4) { 144 | // Noting R(i) = GetRing(ring_index + i, view_azimuth), computes the value 145 | // R(0) such that the second derivative at -1, R(-2) - 2R(-1) + R(0) is 146 | // equal to the second derivative at -2, R(-3) - 2R(-2) + R(-1). 147 | return GetRing(ring_index - 3, view_azimuth) - 148 | GetRing(ring_index - 2, view_azimuth) * 3.0 + 149 | GetRing(ring_index - 1, view_azimuth) * 3.0; 150 | } else { 151 | // Normal case: cubic interpolation of the nearest samples along the ring. 152 | double u = view_azimuth.to(dimensional::pi) * (4 * ring_index); 153 | int i = std::floor(u); 154 | u -= i; 155 | return Cubic(u, GetRing(ring_index, i - 1), GetRing(ring_index, i), 156 | GetRing(ring_index, i + 1), GetRing(ring_index, i + 2)); 157 | } 158 | } 159 | 160 | // Returns the value of the sample point designated by the given ring index 161 | // (0 is for the zenith sample 4,4, 1 is for samples 5,4 5,5 4,5 3,5 3,4 etc, 162 | // and so on up to ring index 4) and index in ring (0 is for azimuth 0, 163 | // ring_index for azimuth 45, k * ring_index for azimuth k * 45). 164 | const T& GetRing(int ring_index, int index_in_ring) const { 165 | assert(ring_index >= 0 && ring_index < 5); 166 | if (ring_index == 0) { 167 | return value_[4][4]; 168 | } else { 169 | while (index_in_ring < 0) { 170 | index_in_ring += 8 * ring_index; 171 | } 172 | int dx = std::max(-ring_index, std::min(ring_index, 173 | std::abs(index_in_ring % (8 * ring_index) - 4 * ring_index) - 174 | 2 * ring_index)); 175 | int dy = std::max(-ring_index, std::min(ring_index, 176 | std::abs((index_in_ring + 6 * ring_index) % (8 * ring_index) - 177 | 4 * ring_index) - 2 * ring_index)); 178 | return value_[4 + dx][4 + dy]; 179 | } 180 | } 181 | 182 | // Returns the derivative of the interpolated function at the zenith, in 183 | // direction view_azimuth. For this, estimates the derivatives in the x and y 184 | // directions from the 8 samples around the zenith, and returns a linear 185 | // combination of those depending on the azimuth angle. 186 | T GetZenithDerivative(Angle view_azimuth) const { 187 | constexpr double norm = 1.0 / sqrt(2.0); 188 | constexpr double scale = 0.5 / (1.0 + 2.0 * norm); 189 | T derivative_x = ((value_[5][4] - value_[3][4]) + 190 | (value_[5][5] - value_[3][3]) * norm + 191 | (value_[5][3] - value_[3][5]) * norm) * scale; 192 | T derivative_y = ((value_[4][5] - value_[4][3]) + 193 | (value_[5][5] - value_[3][3]) * norm + 194 | (value_[3][5] - value_[5][3]) * norm) * scale; 195 | return 196 | derivative_x * cos(view_azimuth)() + derivative_y * sin(view_azimuth)(); 197 | } 198 | 199 | static T Cubic(double u, T am1, T a0, T a1, T a2) { 200 | return (a0 * 2.0 + ((-am1 + a1) + ((am1 * 2.0 - a0 * 5.0 + a1 * 4.0 - a2) + 201 | (-am1 + a0 * 3.0 - a1 * 3.0 + a2) * u) * u) * u) * 0.5; 202 | } 203 | 204 | // The function values in the unit square, mapped to the hemisphere using 205 | // "A low distortion map between disk and square.", Hirley et al. 1997. The 206 | // positive x axis corresponds to azimuth 0 (North), and the positive y axis 207 | // to azimuth 90 (East). More precisely, element [4][4] corresponds to the 208 | // zenith, element [8][4] corresponds to azimuth 0 and elevation 12.1151 from 209 | // the horizon, and element[4][8] to azimuth 90 and the same elevation. 210 | T value_[9][9]; 211 | }; 212 | 213 | #endif // ATMOSPHERE_HEMISPHERICAL_FUNCTION_H_ 214 | -------------------------------------------------------------------------------- /atmosphere/hemispherical_function_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/hemispherical_function.h" 31 | 32 | #include 33 | 34 | #include "test/test_case.h" 35 | 36 | class TestHemisphericalFunction : public dimensional::TestCase { 37 | public: 38 | template 39 | TestHemisphericalFunction(const std::string& name, T test) 40 | : TestCase("TestHemisphericalFunction " + name, static_cast(test)) { 41 | } 42 | 43 | void TestGetSet() { 44 | HemisphericalFunction f; 45 | for (int i = 0; i < 9; ++i) { 46 | for (int j = 0; j < 9; ++j) { 47 | f.Set(i, j, i * 10 + j); 48 | } 49 | } 50 | for (int i = 0; i < 9; ++i) { 51 | for (int j = 0; j < 9; ++j) { 52 | ExpectEquals(i * 10 + j, f.Get(i, j)); 53 | } 54 | } 55 | } 56 | 57 | void TestGetSampleDirection() { 58 | Angle view_zenith; 59 | Angle view_azimuth; 60 | HemisphericalFunction::GetSampleDirection( 61 | 4, 4, &view_zenith, &view_azimuth); 62 | ExpectNear(0.0, view_zenith.to(deg), 1e-9); 63 | 64 | HemisphericalFunction::GetSampleDirection( 65 | 8, 4, &view_zenith, &view_azimuth); 66 | ExpectNear(90.0 - 12.1151, view_zenith.to(deg), 1e-4); 67 | ExpectNear(0.0, view_azimuth.to(deg), 1e-4); 68 | 69 | HemisphericalFunction::GetSampleDirection( 70 | 4, 7, &view_zenith, &view_azimuth); 71 | ExpectNear(90.0 - 33.749, view_zenith.to(deg), 1e-4); 72 | ExpectNear(90.0, view_azimuth.to(deg), 1e-4); 73 | 74 | HemisphericalFunction::GetSampleDirection( 75 | 2, 4, &view_zenith, &view_azimuth); 76 | ExpectNear(90.0 - 53.3665, view_zenith.to(deg), 1e-4); 77 | ExpectNear(180.0, view_azimuth.to(deg), 1e-4); 78 | 79 | HemisphericalFunction::GetSampleDirection( 80 | 4, 3, &view_zenith, &view_azimuth); 81 | ExpectNear(90.0 - 71.9187, view_zenith.to(deg), 1e-4); 82 | ExpectNear(270.0, view_azimuth.to(deg), 1e-4); 83 | } 84 | 85 | void TestInterpolation() { 86 | HemisphericalFunction f; 87 | for (int i = 0; i < 9; ++i) { 88 | for (int j = 0; j < 9; ++j) { 89 | f.Set(i, j, i * 10 + j); 90 | } 91 | } 92 | for (int i = 0; i < 9; ++i) { 93 | for (int j = 0; j < 9; ++j) { 94 | Angle view_zenith; 95 | Angle view_azimuth; 96 | HemisphericalFunction::GetSampleDirection( 97 | i, j, &view_zenith, &view_azimuth); 98 | ExpectNear(i * 10 + j, f(view_zenith, view_azimuth), 1e-8); 99 | ExpectNear(i * 10 + j, f(view_zenith, view_azimuth - 2 * pi), 1e-8); 100 | ExpectNear(i * 10 + j, f(view_zenith, view_azimuth + 2 * pi), 1e-8); 101 | } 102 | } 103 | ExpectNear(84.5, f((90.0 - 12.1151) * deg, (90.0 / 16.0) * deg), 1e-1); 104 | ExpectNear( 105 | 69.0, f((90.0 - (53.3665 + 33.749) * 0.5) * deg, 0.0 * deg), 1e-1); 106 | } 107 | 108 | void TestLoadSave() { 109 | HemisphericalFunction f; 110 | for (int i = 0; i < 9; ++i) { 111 | for (int j = 0; j < 9; ++j) { 112 | f.Set(i, j, i * 10 + j); 113 | } 114 | } 115 | f.Save("output/Debug/hemispherical_fuction_test.dat"); 116 | 117 | f = HemisphericalFunction(); 118 | 119 | f.Load("output/Debug/hemispherical_fuction_test.dat"); 120 | for (int i = 0; i < 9; ++i) { 121 | for (int j = 0; j < 9; ++j) { 122 | ExpectEquals(i * 10 + j, f.Get(i, j)); 123 | } 124 | } 125 | } 126 | }; 127 | 128 | namespace { 129 | 130 | TestHemisphericalFunction getset( 131 | "getset", &TestHemisphericalFunction::TestGetSet); 132 | TestHemisphericalFunction getsampledirection( 133 | "getsampledirection", &TestHemisphericalFunction::TestGetSampleDirection); 134 | TestHemisphericalFunction interpolation( 135 | "interpolation", &TestHemisphericalFunction::TestInterpolation); 136 | TestHemisphericalFunction loadsave( 137 | "loadsave", &TestHemisphericalFunction::TestLoadSave); 138 | 139 | } // anonymous namespace 140 | 141 | -------------------------------------------------------------------------------- /atmosphere/measurement/measured_atmosphere.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERE_H_ 31 | #define ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERE_H_ 32 | 33 | #include 34 | 35 | #include "atmosphere/atmosphere.h" 36 | #include "atmosphere/hemispherical_function.h" 37 | #include "math/angle.h" 38 | #include "physics/units.h" 39 | 40 | class MeasuredAtmosphere : public Atmosphere { 41 | public: 42 | MeasuredAtmosphere(const std::string& directory, const std::string& date, 43 | const std::string& hour, const std::string& minutes, Angle sun_zenith, 44 | Angle sun_azimuth, const std::string& cache_directory, 45 | bool compute_azimuth_from_data = true); 46 | 47 | std::string GetSourceFileName(int i, int j) const; 48 | std::string GetSourceFileName(Angle view_zenith, Angle view_azimuth) const; 49 | 50 | inline const Angle sun_zenith() const { return sun_zenith_; } 51 | inline const Angle sun_azimuth() const { return sun_azimuth_; } 52 | 53 | IrradianceSpectrum GetSunIrradiance(Length altitude, 54 | Angle sun_zenith) const; 55 | 56 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 57 | Angle view_zenith, Angle view_sun_azimuth) const; 58 | 59 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 60 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 61 | 62 | // Same as GetSkyRadiance, but returns 0 for view directions that were not 63 | // measured directly, instead of interpolating the neasest samples. 64 | RadianceSpectrum GetSkyRadianceMeasurement(Length altitude, Angle sun_zenith, 65 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 66 | 67 | private: 68 | Radiance GetAxiSymmetryError(Angle axis_azimuth) const; 69 | Angle EstimateSunAzimuth(Angle initial_azimuth) const; 70 | 71 | std::string directory_; 72 | std::string date_; 73 | std::string hour_; 74 | std::string minutes_; 75 | Angle sun_zenith_; 76 | Angle sun_azimuth_; 77 | HemisphericalFunction measurements_; 78 | }; 79 | 80 | #endif // ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERE_H_ 81 | -------------------------------------------------------------------------------- /atmosphere/measurement/measured_atmosphere_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/measurement/measured_atmosphere.h" 31 | 32 | #include 33 | 34 | #include "test/test_case.h" 35 | 36 | class TestMeasuredAtmosphere : public dimensional::TestCase { 37 | public: 38 | template 39 | TestMeasuredAtmosphere(const std::string& name, T test) 40 | : TestCase("TestMeasuredAtmosphere " + name, static_cast(test)) {} 41 | 42 | void TestLoadKiderData() { 43 | MeasuredAtmosphere atmosphere( 44 | "atmosphere/measurement/testdata", "2013-05-27", "11", "45", 45 | 1.0 * deg, 2.0* deg, "", false /* compute_azimuth_from_data */); 46 | SpectralRadiance sr1 = atmosphere.GetSkyRadiance(0 * m, 1 * deg, 2 * deg, 47 | (90.0 - 12.1151) * deg, (360.0 - 326.25) * deg)(400.0 * nm); 48 | SpectralRadiance sr2 = atmosphere.GetSkyRadiance(0 * m, 1 * deg, 2 * deg, 49 | (90.0 - 53.3665) * deg, (360.0 - 67.5) * deg)(400.0 * nm); 50 | SpectralRadiance sr3 = atmosphere.GetSkyRadiance(0 * m, 1 * deg, 2 * deg, 51 | (90.0 - 53.3665) * deg, (360.0 - 225.0) * deg)(400.0 * nm); 52 | SpectralRadiance sr4 = atmosphere.GetSkyRadiance(0 * m, 1 * deg, 2 * deg, 53 | (90.0 - 12.1151) * deg, (360.0 - 225.0) * deg)(400.0 * nm); 54 | ExpectNear(29, sr1.to(watt_per_square_meter_per_sr_per_nm), 1e-3); 55 | ExpectNear(59, sr2.to(watt_per_square_meter_per_sr_per_nm), 1e-3); 56 | ExpectNear(66, sr3.to(watt_per_square_meter_per_sr_per_nm), 1e-3); 57 | ExpectNear(20, sr4.to(watt_per_square_meter_per_sr_per_nm), 1e-3); 58 | } 59 | }; 60 | 61 | namespace { 62 | 63 | TestMeasuredAtmosphere loadkiderdata( 64 | "loadkiderdata", &TestMeasuredAtmosphere::TestLoadKiderData); 65 | 66 | } // anonymous namespace 67 | -------------------------------------------------------------------------------- /atmosphere/measurement/measured_atmospheres.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/measurement/measured_atmospheres.h" 31 | 32 | void MeasuredAtmospheres::AddAtmosphere(const MeasuredAtmosphere* atmosphere) { 33 | measurements_.push_back( 34 | std::unique_ptr(atmosphere)); 35 | } 36 | 37 | IrradianceSpectrum MeasuredAtmospheres::GetSunIrradiance(Length altitude, 38 | Angle sun_zenith) const { 39 | for (unsigned int i = 0; i < measurements_.size(); ++i) { 40 | if (measurements_[i]->sun_zenith() == sun_zenith) { 41 | return measurements_[i]->GetSunIrradiance(altitude, sun_zenith); 42 | } 43 | } 44 | assert(false); 45 | return IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm); 46 | } 47 | 48 | RadianceSpectrum MeasuredAtmospheres::GetSkyRadiance(Length altitude, 49 | Angle sun_zenith, Angle view_zenith, Angle view_sun_azimuth) const { 50 | for (unsigned int i = 0; i < measurements_.size(); ++i) { 51 | if (measurements_[i]->sun_zenith() == sun_zenith) { 52 | return measurements_[i]->GetSkyRadiance( 53 | altitude, sun_zenith, view_zenith, view_sun_azimuth); 54 | } 55 | } 56 | assert(false); 57 | return RadianceSpectrum(0.0 * watt_per_square_meter_per_sr_per_nm); 58 | } 59 | 60 | RadianceSpectrum MeasuredAtmospheres::GetSkyRadiance(Length altitude, 61 | Angle sun_zenith, Angle sun_azimuth, Angle view_zenith, 62 | Angle view_azimuth) const { 63 | for (unsigned int i = 0; i < measurements_.size(); ++i) { 64 | if (measurements_[i]->sun_zenith() == sun_zenith && 65 | measurements_[i]->sun_azimuth() == sun_azimuth) { 66 | return measurements_[i]->GetSkyRadiance( 67 | altitude, sun_zenith, sun_azimuth, view_zenith, view_azimuth); 68 | } 69 | } 70 | assert(false); 71 | return RadianceSpectrum(0.0 * watt_per_square_meter_per_sr_per_nm); 72 | } 73 | 74 | RadianceSpectrum MeasuredAtmospheres::GetSkyRadianceMeasurement(Length altitude, 75 | Angle sun_zenith, Angle sun_azimuth, Angle view_zenith, 76 | Angle view_azimuth) const { 77 | for (unsigned int i = 0; i < measurements_.size(); ++i) { 78 | if (measurements_[i]->sun_zenith() == sun_zenith && 79 | measurements_[i]->sun_azimuth() == sun_azimuth) { 80 | return measurements_[i]->GetSkyRadianceMeasurement( 81 | altitude, sun_zenith, sun_azimuth, view_zenith, view_azimuth); 82 | } 83 | } 84 | assert(false); 85 | return RadianceSpectrum(0.0 * watt_per_square_meter_per_sr_per_nm); 86 | } 87 | 88 | IrradianceSpectrum MeasuredAtmospheres::GetSkyIrradiance(Length altitude, 89 | Angle sun_zenith) const { 90 | for (unsigned int i = 0; i < measurements_.size(); ++i) { 91 | if (measurements_[i]->sun_zenith() == sun_zenith) { 92 | return measurements_[i]->GetSkyIrradiance(altitude, sun_zenith); 93 | } 94 | } 95 | assert(false); 96 | return IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm); 97 | } 98 | -------------------------------------------------------------------------------- /atmosphere/measurement/measured_atmospheres.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERES_H_ 31 | #define ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERES_H_ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include "atmosphere/atmosphere.h" 38 | #include "atmosphere/measurement/measured_atmosphere.h" 39 | #include "math/angle.h" 40 | #include "physics/units.h" 41 | 42 | class MeasuredAtmospheres : public Atmosphere { 43 | public: 44 | // Takes ownership of the given object. 45 | void AddAtmosphere(const MeasuredAtmosphere* atmosphere); 46 | 47 | IrradianceSpectrum GetSunIrradiance(Length altitude, 48 | Angle sun_zenith) const; 49 | 50 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 51 | Angle view_zenith, Angle view_sun_azimuth) const; 52 | 53 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 54 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 55 | 56 | // Same as GetSkyRadiance, but returns 0 for view directions that were not 57 | // measured directly, instead of interpolating the neasest samples. 58 | RadianceSpectrum GetSkyRadianceMeasurement(Length altitude, Angle sun_zenith, 59 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 60 | 61 | IrradianceSpectrum GetSkyIrradiance(Length altitude, 62 | Angle sun_zenith) const; 63 | 64 | private: 65 | std::vector> measurements_; 66 | }; 67 | 68 | #endif // ATMOSPHERE_MEASUREMENT_MEASURED_ATMOSPHERES_H_ 69 | 70 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_0____0.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_10____112.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_11____123.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_12____135.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_13____146.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_14____157.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_15____168.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_16____180.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_17____191.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_18____202.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_19____213.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_1____11.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_20____225.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 20.0 3 | 4000 20.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_21____236.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_22____247.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_23____258.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_24____270.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_25____281.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_26____292.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_27____303.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_28____315.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_29____326.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 29.0 3 | 4000 29.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_2____22.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_30____337.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_31____348.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_32____345.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_33____330.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_34____315.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_35____300.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_36____285.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_37____270.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_38____255.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_39____240.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_3____33.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_40____225.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_41____210.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_42____195.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_43____180.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_44____165.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_45____150.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_46____135.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_47____120.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_48____105.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_49____90.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_4____45.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_50____75.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_51____60.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_52____45.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_53____30.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_54____15.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_55____0.0___33.749.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_56____0.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_57____22.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_58____45.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_59____67.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 59.0 3 | 4000 59.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_5____56.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_60____90.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_61____112.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_62____135.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_63____157.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_64____180.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_65____202.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_66____225.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 66.0 3 | 4000 66.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_67____247.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_68____270.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_69____292.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_6____67.5___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_70____315.0___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_71____337.5___53.3665.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_72____315.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_73____270.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_74____225.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_75____180.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_76____135.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_77____90.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_78____45.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_79____0.0___71.9187.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_7____78.75___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_80____0.0___90.0.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_8____90.0___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/measurement/testdata/2013-05-27___11.45.00/2013-05-27___11.45.00_-_9____101.25___12.1151.asd.rad.txt: -------------------------------------------------------------------------------- 1 | Wavelength Radiance 2 | 350 0.0 3 | 4000 0.0 4 | 5 | -------------------------------------------------------------------------------- /atmosphere/model/bruneton/bruneton.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/bruneton/bruneton.h" 31 | 32 | #include 33 | #include 34 | 35 | #include "atmosphere/model/bruneton/core.h" 36 | 37 | Bruneton::Bruneton(ScatteringType scattering_type, 38 | int original_number_of_wavelength) 39 | : original_number_of_wavelength_(original_number_of_wavelength) { 40 | std::ifstream f; 41 | std::string name; 42 | const std::string cache_directory = "output/cache/bruneton/"; 43 | 44 | name = cache_directory + "transmittance.dat"; 45 | f.open(name); 46 | if (f.good()) { 47 | f.close(); 48 | transmittance_sampler_.Load(name); 49 | } else { 50 | ComputeTransmittance(&transmittance_sampler_); 51 | transmittance_sampler_.Save(name); 52 | } 53 | 54 | constexpr int kNumScatteringOrders = 4; 55 | constexpr int kNumSteps = 2 * kNumScatteringOrders - 1; 56 | 57 | if (scattering_type == DOUBLE_SCATTERING_ONLY) { 58 | inscatter1R_sampler_.Set( 59 | IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm)); 60 | inscatter1M_sampler_.Set( 61 | IrradianceSpectrum(0.0 * watt_per_square_meter_per_nm)); 62 | } else { 63 | name = cache_directory + "inscatter1R.dat"; 64 | f.open(name); 65 | if (f.good()) { 66 | f.close(); 67 | inscatter1R_sampler_.Load(name); 68 | inscatter1M_sampler_.Load(cache_directory + "inscatter1M.dat"); 69 | } else { 70 | std::cout << "Precomputing, step 1/" << kNumSteps << "..." << std::endl; 71 | ComputeInscatter1(transmittance_sampler_, &inscatter1R_sampler_, 72 | &inscatter1M_sampler_); 73 | inscatter1R_sampler_.Save(name); 74 | inscatter1M_sampler_.Save(cache_directory + "inscatter1M.dat"); 75 | } 76 | } 77 | 78 | if (scattering_type == SINGLE_SCATTERING_ONLY) { 79 | inscatterN_sum_sampler_.Set( 80 | RadianceSpectrum(0.0 * watt_per_square_meter_per_sr_per_nm)); 81 | name = cache_directory + "irradiance2.dat"; 82 | f.open(name); 83 | if (f.good()) { 84 | f.close(); 85 | sky_irradiance_sum_sampler_.Load(name); 86 | } else { 87 | std::cerr << name << " must be precomputed. Run with ALL_ORDERS first." 88 | << std::endl; 89 | exit(-1); 90 | } 91 | return; 92 | } else if (scattering_type == DOUBLE_SCATTERING_ONLY) { 93 | name = cache_directory + "inscatter2.dat"; 94 | f.open(name); 95 | if (f.good()) { 96 | f.close(); 97 | inscatterN_sum_sampler_.Load(name); 98 | sky_irradiance_sum_sampler_.Load(cache_directory + "irradiance3.dat"); 99 | } else { 100 | std::cerr << name << " must be precomputed. Run with ALL_ORDERS first." 101 | << std::endl; 102 | exit(-1); 103 | } 104 | return; 105 | } else { 106 | name = cache_directory + "inscatterNSum.dat"; 107 | f.open(name); 108 | if (f.good()) { 109 | f.close(); 110 | inscatterN_sum_sampler_.Load(name); 111 | sky_irradiance_sum_sampler_.Load(cache_directory + "irradianceNSum.dat"); 112 | return; 113 | } 114 | } 115 | 116 | SkyIrradianceTexture sky_irradiance_sampler; 117 | name = cache_directory + "irradiance1.dat"; 118 | f.open(name); 119 | if (f.good()) { 120 | f.close(); 121 | sky_irradiance_sampler.Load(name); 122 | } else { 123 | ComputeSkyIrradiance1(transmittance_sampler_, &sky_irradiance_sampler); 124 | sky_irradiance_sampler.Save(name); 125 | } 126 | 127 | RadianceDensityTexture inscatterS_sampler; 128 | RadianceTexture inscatterN_sampler; 129 | for (int i = 2; i <= kNumScatteringOrders; ++i) { 130 | const std::string iteration = std::to_string(i); 131 | bool first_iteration = i == 2; 132 | 133 | name = cache_directory + "inscatterS" + iteration + ".dat"; 134 | f.open(name); 135 | if (f.good()) { 136 | f.close(); 137 | inscatterS_sampler.Load(name); 138 | } else { 139 | std::cout << "Precomputing, step " << 2 * i - 2 << "/" << kNumSteps 140 | << "..." << std::endl; 141 | ComputeInscatterS(transmittance_sampler_, sky_irradiance_sampler, 142 | inscatter1R_sampler_, inscatter1M_sampler_, inscatterN_sampler, 143 | first_iteration, &inscatterS_sampler); 144 | inscatterS_sampler.Save(name); 145 | } 146 | 147 | name = cache_directory + "irradiance" + iteration + ".dat"; 148 | f.open(name); 149 | if (f.good()) { 150 | f.close(); 151 | sky_irradiance_sampler.Load(name); 152 | } else { 153 | ComputeSkyIrradianceN(inscatter1R_sampler_, inscatter1M_sampler_, 154 | inscatterN_sampler, first_iteration, &sky_irradiance_sampler); 155 | sky_irradiance_sampler.Save(name); 156 | } 157 | 158 | name = cache_directory + "inscatter" + iteration + ".dat"; 159 | f.open(name); 160 | if (f.good()) { 161 | f.close(); 162 | inscatterN_sampler.Load(name); 163 | } else { 164 | std::cout << "Precomputing, step " << 2 * i - 1 << "/" << kNumSteps 165 | << "..." << std::endl; 166 | ComputeInscatterN(transmittance_sampler_, inscatterS_sampler, 167 | &inscatterN_sampler); 168 | inscatterN_sampler.Save(name); 169 | } 170 | 171 | if (first_iteration) { 172 | sky_irradiance_sum_sampler_.Set(sky_irradiance_sampler); 173 | inscatterN_sum_sampler_.Set(inscatterN_sampler); 174 | } else { 175 | sky_irradiance_sum_sampler_ += sky_irradiance_sampler; 176 | inscatterN_sum_sampler_ += inscatterN_sampler; 177 | } 178 | } 179 | inscatterN_sum_sampler_.Save(cache_directory + "inscatterNSum.dat"); 180 | sky_irradiance_sum_sampler_.Save(cache_directory + "irradianceNSum.dat"); 181 | } 182 | 183 | IrradianceSpectrum Bruneton::GetSunIrradiance(Length altitude, 184 | Angle sun_zenith) const { 185 | return GetTransmittance(transmittance_sampler_, EarthRadius + altitude, 186 | cos(sun_zenith)) * SolarSpectrum(); 187 | } 188 | 189 | RadianceSpectrum Bruneton::GetSkyRadiance(Length altitude, Angle sun_zenith, 190 | Angle view_zenith, Angle view_sun_azimuth) const { 191 | Number mu_s = cos(sun_zenith); 192 | Number mu = cos(view_zenith); 193 | Number nu = 194 | cos(view_sun_azimuth) * sin(view_zenith) * sin(sun_zenith) + mu * mu_s; 195 | InverseSolidAngle rayleigh_phase = RayleighPhaseFunction(nu); 196 | InverseSolidAngle mie_phase = MiePhaseFunction(nu); 197 | 198 | IrradianceSpectrum ray = 199 | texture4d(inscatter1R_sampler_, EarthRadius + altitude, mu, mu_s, nu); 200 | IrradianceSpectrum mie = 201 | texture4d(inscatter1M_sampler_, EarthRadius + altitude, mu, mu_s, nu); 202 | RadianceSpectrum raymieN = 203 | texture4d(inscatterN_sum_sampler_, EarthRadius + altitude, mu, mu_s, nu); 204 | return (ray * rayleigh_phase + mie * mie_phase) + raymieN; 205 | } 206 | 207 | IrradianceSpectrum Bruneton::GetSkyIrradiance(Length altitude, 208 | Angle sun_zenith) const { 209 | return ::GetSkyIrradiance( 210 | sky_irradiance_sum_sampler_, EarthRadius + altitude, cos(sun_zenith)); 211 | } 212 | -------------------------------------------------------------------------------- /atmosphere/model/bruneton/bruneton.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_BRUNETON_BRUNETON_H_ 31 | #define ATMOSPHERE_MODEL_BRUNETON_BRUNETON_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "atmosphere/model/bruneton/core.h" 35 | #include "math/angle.h" 36 | #include "physics/units.h" 37 | 38 | class Bruneton : public Atmosphere { 39 | public: 40 | enum ScatteringType { 41 | SINGLE_SCATTERING_ONLY, DOUBLE_SCATTERING_ONLY, ALL_ORDERS 42 | }; 43 | 44 | // Use 3 wavelength for the Bruneton model, 15 for the Elek model. 45 | Bruneton(ScatteringType scattering_type, int original_number_of_wavelength); 46 | 47 | int GetOriginalNumberOfWavelengths() const override { 48 | return original_number_of_wavelength_; 49 | } 50 | 51 | IrradianceSpectrum GetSunIrradiance(Length altitude, 52 | Angle sun_zenith) const override; 53 | 54 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 55 | Angle view_zenith, Angle view_sun_azimuth) const override; 56 | 57 | IrradianceSpectrum GetSkyIrradiance(Length altitude, 58 | Angle sun_zenith) const override; 59 | 60 | private: 61 | int original_number_of_wavelength_; 62 | TransmittanceTexture transmittance_sampler_; 63 | IrradianceTexture inscatter1R_sampler_; 64 | IrradianceTexture inscatter1M_sampler_; 65 | RadianceTexture inscatterN_sum_sampler_; 66 | SkyIrradianceTexture sky_irradiance_sum_sampler_; 67 | }; 68 | 69 | #endif // ATMOSPHERE_MODEL_BRUNETON_BRUNETON_H_ 70 | -------------------------------------------------------------------------------- /atmosphere/model/bruneton/core.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/bruneton/core.h" 31 | 32 | #include "atmosphere/atmosphere.h" 33 | #include "util/progress_bar.h" 34 | 35 | using dimensional::vec2; 36 | using dimensional::vec3; 37 | using std::max; 38 | using std::min; 39 | 40 | constexpr Length Rg = EarthRadius; 41 | constexpr Length Rt = AtmosphereRadius; 42 | constexpr Length RL = Rt + 1.0 * km; 43 | 44 | constexpr Length HR = RayleighScaleHeight; 45 | constexpr Length HM = MieScaleHeight; 46 | 47 | #include "atmosphere/model/bruneton/core.inl" 48 | 49 | void SetLayer(int layer, Length* r, Length* dmin, Length* dmax, Length* dminp, 50 | Length* dmaxp) { 51 | double u = (layer * layer) / ((RES_R - 1.0) * (RES_R - 1.0)); 52 | *r = sqrt(Rg * Rg + u * (Rt * Rt - Rg * Rg)) + 53 | (layer == 0 ? 0.01 : (layer == RES_R - 1 ? -0.001 : 0.0)) * km; 54 | *dmin = Rt - *r; 55 | *dmax = sqrt((*r) * (*r) - Rg * Rg) + sqrt(Rt * Rt - Rg * Rg); 56 | *dminp = *r - Rg; 57 | *dmaxp = sqrt((*r) * (*r) - Rg * Rg); 58 | } 59 | 60 | void ComputeTransmittance(TransmittanceTexture* transmittance_sampler) { 61 | for (unsigned int j = 0; j < TRANSMITTANCE_H; ++j) { 62 | for (unsigned int i = 0; i < TRANSMITTANCE_W; ++i) { 63 | transmittance_sampler->Set( 64 | i, j, ComputeTransmittance(vec2(i + 0.5, j + 0.5))); 65 | } 66 | } 67 | } 68 | 69 | void ComputeSkyIrradiance1(const TransmittanceTexture& transmittance_sampler, 70 | SkyIrradianceTexture* sky_irradiance) { 71 | for (unsigned int j = 0; j < IRRADIANCE_H; ++j) { 72 | for (unsigned int i = 0; i < IRRADIANCE_W; ++i) { 73 | sky_irradiance->Set(i, j, ComputeSkyIrradiance1( 74 | transmittance_sampler, vec2(i + 0.5, j + 0.5))); 75 | } 76 | } 77 | } 78 | 79 | void ComputeInscatter1(const TransmittanceTexture& transmittance_sampler, 80 | IrradianceTexture* rayleigh_single_scatter_sampler, 81 | IrradianceTexture* mie_single_scatter_sampler) { 82 | ProgressBar progress_bar(RES_R * RES_MU * RES_MU_S * RES_NU); 83 | RunJobs([&](unsigned int k) { 84 | Length r, dmin, dmax, dminp, dmaxp; 85 | SetLayer(k, &r, &dmin, &dmax, &dminp, &dmaxp); 86 | for (unsigned int j = 0; j < RES_MU; ++j) { 87 | for (unsigned int i = 0; i < RES_MU_S * RES_NU; ++i) { 88 | IrradianceSpectrum ray; 89 | IrradianceSpectrum mie; 90 | ComputeInscatter1(transmittance_sampler, r, dmin, dmax, dminp, dmaxp, 91 | vec2(i + 0.5, j + 0.5), &ray, &mie); 92 | rayleigh_single_scatter_sampler->Set(i, j, k, ray); 93 | mie_single_scatter_sampler->Set(i, j, k, mie); 94 | progress_bar.Increment(1); 95 | } 96 | } 97 | }, RES_R); 98 | } 99 | 100 | void ComputeInscatterS(const TransmittanceTexture& transmittance_sampler, 101 | const SkyIrradianceTexture& sky_irradiance_texture, 102 | const IrradianceTexture& rayleigh_sampler, 103 | const IrradianceTexture& mie_sampler, const RadianceTexture& raymie_sampler, 104 | bool first_iteration, RadianceDensityTexture* raymie) { 105 | ProgressBar progress_bar(RES_R * RES_MU * RES_MU_S * RES_NU); 106 | RunJobs([&](unsigned int k) { 107 | Length r, dmin, dmax, dminp, dmaxp; 108 | SetLayer(k, &r, &dmin, &dmax, &dminp, &dmaxp); 109 | for (unsigned int j = 0; j < RES_MU; ++j) { 110 | for (unsigned int i = 0; i < RES_MU_S * RES_NU; ++i) { 111 | RadianceDensitySpectrum inscatterS; 112 | ComputeInscatterS(transmittance_sampler, sky_irradiance_texture, 113 | rayleigh_sampler, mie_sampler, raymie_sampler, 114 | r, dmin, dmax, dminp, dmaxp, vec2(i + 0.5, j + 0.5), 115 | first_iteration, &inscatterS); 116 | raymie->Set(i, j, k, inscatterS); 117 | progress_bar.Increment(1); 118 | } 119 | } 120 | }, RES_R); 121 | } 122 | 123 | void ComputeSkyIrradianceN(const IrradianceTexture& rayleigh_sampler, 124 | const IrradianceTexture& mie_sampler, const RadianceTexture& raymie_sampler, 125 | bool first_iteration, SkyIrradianceTexture* sky_irradiance) { 126 | for (unsigned int j = 0; j < IRRADIANCE_H; ++j) { 127 | for (unsigned int i = 0; i < IRRADIANCE_W; ++i) { 128 | sky_irradiance->Set(i, j, ComputeSkyIrradianceN(rayleigh_sampler, 129 | mie_sampler, raymie_sampler, vec2(i + 0.5, j + 0.5), 130 | first_iteration)); 131 | } 132 | } 133 | } 134 | 135 | void ComputeInscatterN(const TransmittanceTexture& transmittance_sampler, 136 | const RadianceDensityTexture& radiance_density_sampler, 137 | RadianceTexture* raymie) { 138 | ProgressBar progress_bar(RES_R * RES_MU * RES_MU_S * RES_NU); 139 | RunJobs([&](unsigned int k) { 140 | Length r, dmin, dmax, dminp, dmaxp; 141 | SetLayer(k, &r, &dmin, &dmax, &dminp, &dmaxp); 142 | for (unsigned int j = 0; j < RES_MU; ++j) { 143 | for (unsigned int i = 0; i < RES_MU_S * RES_NU; ++i) { 144 | RadianceSpectrum inscatterN; 145 | ComputeInscatterN(transmittance_sampler, radiance_density_sampler, 146 | r, dmin, dmax, dminp, dmaxp, vec2(i + 0.5, j + 0.5), &inscatterN); 147 | raymie->Set(i, j, k, inscatterN); 148 | progress_bar.Increment(1); 149 | } 150 | } 151 | }, RES_R); 152 | } 153 | -------------------------------------------------------------------------------- /atmosphere/model/bruneton/core.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_BRUNETON_CORE_H_ 31 | #define ATMOSPHERE_MODEL_BRUNETON_CORE_H_ 32 | 33 | #include 34 | 35 | #include "atmosphere/atmosphere.h" 36 | #include "math/binary_function.h" 37 | #include "math/scalar.h" 38 | #include "math/ternary_function.h" 39 | #include "math/vector.h" 40 | #include "physics/units.h" 41 | 42 | Length Limit(Length r, Number mu); 43 | 44 | // TRANSMITTANCE -------------------------------------------------------------- 45 | 46 | // Texture size for the transmittance texture T. 47 | const unsigned int TRANSMITTANCE_W = 256; 48 | const unsigned int TRANSMITTANCE_H = 64; 49 | 50 | typedef dimensional::BinaryFunction< 51 | TRANSMITTANCE_W, TRANSMITTANCE_H, DimensionlessSpectrum> 52 | TransmittanceTexture; 53 | 54 | DimensionlessSpectrum GetTransmittance( 55 | const TransmittanceTexture& transmittance_sampler, Length r, Number mu); 56 | 57 | DimensionlessSpectrum GetTransmittance( 58 | const TransmittanceTexture& transmittance_sampler, Length r, Number mu, 59 | Length d); 60 | 61 | // SKY IRRADIANCE -------------------------------------------------------------- 62 | 63 | // Texture size for the sky irradiance textures E and DeltaE. 64 | const unsigned int IRRADIANCE_W = 64; 65 | const unsigned int IRRADIANCE_H = 16; 66 | 67 | typedef dimensional::BinaryFunction< 68 | IRRADIANCE_W, IRRADIANCE_H, IrradianceSpectrum> 69 | SkyIrradianceTexture; 70 | 71 | IrradianceSpectrum GetSkyIrradiance( 72 | const SkyIrradianceTexture& sky_irradiance_sampler, Length r, Number muS); 73 | 74 | // SKY RADIANCE ---------------------------------------------------------------- 75 | 76 | // Texture size for the various 4D textures (S, DeltaS, DeltaJ, etc). 77 | const unsigned int RES_R = 32; 78 | const unsigned int RES_MU = 128; 79 | const unsigned int RES_MU_S = 32; 80 | const unsigned int RES_NU = 8; 81 | 82 | typedef dimensional::Scalar<-3, -1, -1, 1, 0> SpectralRadianceDensity; 83 | 84 | typedef WavelengthFunction<-3, -1, -1, 1, 0> RadianceDensitySpectrum; 85 | 86 | typedef dimensional::TernaryFunction< 87 | RES_MU_S * RES_NU, RES_MU, RES_R, IrradianceSpectrum> 88 | IrradianceTexture; 89 | 90 | typedef dimensional::TernaryFunction< 91 | RES_MU_S * RES_NU, RES_MU, RES_R, RadianceSpectrum> 92 | RadianceTexture; 93 | 94 | typedef dimensional::TernaryFunction< 95 | RES_MU_S * RES_NU, RES_MU, RES_R, RadianceDensitySpectrum> 96 | RadianceDensityTexture; 97 | 98 | // PRECOMPUTATIONS ------------------------------------------------------------- 99 | 100 | DimensionlessSpectrum ComputeTransmittance(dimensional::vec2 xy); 101 | 102 | void ComputeTransmittance(TransmittanceTexture* transmittance_sampler); 103 | 104 | void ComputeSkyIrradiance1(const TransmittanceTexture& transmittance_sampler, 105 | SkyIrradianceTexture* sky_irradiance); 106 | 107 | void ComputeInscatter1(const TransmittanceTexture& transmittance_sampler, 108 | IrradianceTexture* rayleigh_single_scatter_sampler, 109 | IrradianceTexture* mie_single_scatter_sampler); 110 | 111 | void ComputeInscatterS(const TransmittanceTexture& transmittance_sampler, 112 | const SkyIrradianceTexture& sky_irradiance_texture, 113 | const IrradianceTexture& rayleigh_sampler, 114 | const IrradianceTexture& mie_sampler, const RadianceTexture& raymie_sampler, 115 | bool first_iteration, RadianceDensityTexture* raymie); 116 | 117 | void ComputeSkyIrradianceN(const IrradianceTexture& rayleigh_sampler, 118 | const IrradianceTexture& mie_sampler, const RadianceTexture& raymie_sampler, 119 | bool first_iteration, SkyIrradianceTexture* sky_irradiance); 120 | 121 | void ComputeInscatterN(const TransmittanceTexture& transmittance_sampler, 122 | const RadianceDensityTexture& radiance_density_sampler, 123 | RadianceTexture* raymie); 124 | 125 | // TEXTURE FETCH --------------------------------------------------------------- 126 | 127 | template 128 | T texture2d(const dimensional::BinaryFunction& table, 129 | const dimensional::vec2& uv) { 130 | return table(uv.x(), uv.y()); 131 | } 132 | 133 | template 134 | T texture4d(const dimensional::TernaryFunction& table, 135 | Length r, Number mu, Number muS, Number nu) { 136 | const Length H = 137 | sqrt(AtmosphereRadius * AtmosphereRadius - EarthRadius * EarthRadius); 138 | Length rho = sqrt(r * r - EarthRadius * EarthRadius); 139 | Length rmu = r * mu; 140 | Area delta = rmu * rmu - r * r + EarthRadius * EarthRadius; 141 | Number cstx; 142 | Area csty; 143 | Length cstz; 144 | Number cstw; 145 | if (rmu < 0.0 * m && delta > 0.0 * m2) { 146 | cstx = 1.0; 147 | csty = 0.0 * m2; 148 | cstz = 0.0 * m; 149 | cstw = 0.5 - 0.5 / RES_MU; 150 | } else { 151 | cstx = -1.0; 152 | csty = H * H; 153 | cstz = H; 154 | cstw = 0.5 + 0.5 / RES_MU; 155 | } 156 | Number uR = 157 | 0.5 / RES_R + rho / H * (1.0 - 1.0 / RES_R); 158 | Number uMu = cstw + (rmu * cstx + sqrt(delta + csty)) / 159 | (rho + cstz) * (0.5 - 1.0 / RES_MU); 160 | // paper formula 161 | // Number uMuS = 0.5 / RES_MU_S + 162 | // max((1.0 - exp(-3.0 * muS - 0.6)) / (1.0 - exp(-3.6)), 0.0) * 163 | // (1.0 - 1.0 / RES_MU_S); 164 | // better formula 165 | constexpr Angle a = 1.1 * rad; 166 | Number uMuS = 0.5 / RES_MU_S + 167 | (atan(max(muS, -0.1975) * tan(1.26 * a)) / a + (1.0 - 0.26)) * 168 | 0.5 * (1.0 - 1.0 / RES_MU_S); 169 | Number lerp = (nu + 1.0) / 2.0 * (RES_NU - 1); 170 | Number uNu = floor(lerp); 171 | lerp = lerp - uNu; 172 | return table((uNu + uMuS)() / RES_NU, uMu(), uR()) * (1.0 - lerp) + 173 | table((uNu + uMuS + 1.0)() / RES_NU, uMu(), uR()) * lerp; 174 | } 175 | 176 | #endif // ATMOSPHERE_MODEL_BRUNETON_CORE_H_ 177 | -------------------------------------------------------------------------------- /atmosphere/model/haber/haber.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_HABER_HABER_H_ 31 | #define ATMOSPHERE_MODEL_HABER_HABER_H_ 32 | 33 | #include 34 | 35 | #include "atmosphere/atmosphere.h" 36 | #include "math/angle.h" 37 | #include "math/binary_function.h" 38 | #include "math/vector.h" 39 | #include "physics/units.h" 40 | 41 | class Haber : public Atmosphere { 42 | public: 43 | enum ScatteringType { 44 | SINGLE_SCATTERING_ONLY, DOUBLE_SCATTERING_ONLY, ALL_ORDERS 45 | }; 46 | 47 | explicit Haber(ScatteringType scattering_type); 48 | 49 | int GetOriginalNumberOfWavelengths() const override { return 8; } 50 | 51 | IrradianceSpectrum GetSunIrradiance(Length altitude, 52 | Angle sun_zenith) const override; 53 | 54 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 55 | Angle view_zenith, Angle view_sun_azimuth) const override; 56 | 57 | private: 58 | static constexpr int kNumLayers = 50; 59 | static constexpr Length kMaxLayerHeight = 35.0 * km; 60 | 61 | static constexpr int kNumPhi = 72; 62 | static constexpr Angle kDeltaPhi = 2.0 * pi / kNumPhi; 63 | 64 | static constexpr Length kMinShellRadius = 10.0 * m; 65 | static constexpr Length kMaxShellRadius = sqrt( 66 | kMaxLayerHeight * kMaxLayerHeight + 2.0 * EarthRadius * kMaxLayerHeight); 67 | static constexpr Number kShellRatio = 68 | (1.0 + PI / kNumPhi) / (1.0 - PI / kNumPhi); 69 | static constexpr int kNumShell = 70 | ceil((log(kMaxShellRadius / kMinShellRadius) / log(kShellRatio))()); 71 | 72 | static constexpr int kNumTheta = 73 | ceil(((pi / 2.0 + 2.0 * asin(kMaxShellRadius / (2.0 * EarthRadius))) / 74 | kDeltaPhi)()); 75 | 76 | typedef dimensional::Vector3 Position; 77 | typedef dimensional::Vector3 Direction; 78 | 79 | struct Cell { 80 | Position center; 81 | Volume volume; 82 | Length radial_width; 83 | int shell_index; 84 | int layer_index; 85 | PowerSpectrum iso; 86 | PowerSpectrum aniso; 87 | PowerSpectrum last; 88 | PowerSpectrum current; 89 | }; 90 | 91 | void MaybeInit(Angle sun_zenith) const; 92 | void ComputeSingleScatter(Angle sun_zenith) const; 93 | void ComputeMultipleScatter(Angle sun_zenith, bool double_scatter) const; 94 | void InterpolateMultipleScatter(bool double_scatter) const; 95 | void AccumulateMultipleScatter() const; 96 | void ComputeSkyDome(Angle sun_zenith, ScatteringType scattering_type) const; 97 | 98 | DimensionlessSpectrum GetTransmittance(const Position& p, 99 | const Position& q) const; 100 | DimensionlessSpectrum GetTransmittanceSimple(const Position& p, 101 | const Position& q) const; 102 | 103 | static Position GetRayIntersectionWithLastLayer(const Position& p, 104 | Angle view_zenith); 105 | static Length GetLayerHeight(int layer_index); 106 | static int GetLayerIndex(const Position &p); 107 | 108 | ScatteringType scattering_type_; 109 | Number rayleigh_density_[kNumLayers]; 110 | Number mie_density_[kNumLayers]; 111 | mutable Angle current_sun_zenith_; 112 | mutable std::vector cells_[kNumTheta][kNumPhi / 2]; 113 | mutable dimensional::BinaryFunction 114 | sky_dome_; 115 | }; 116 | 117 | #endif // ATMOSPHERE_MODEL_HABER_HABER_H_ 118 | -------------------------------------------------------------------------------- /atmosphere/model/hosek/README.txt: -------------------------------------------------------------------------------- 1 | This file is part of a sample implementation of the analytical skylight and 2 | solar radiance models presented in the SIGGRAPH 2012 paper 3 | 4 | 5 | "An Analytic Model for Full Spectral Sky-Dome Radiance" 6 | 7 | and the 2013 IEEE CG&A paper 8 | 9 | "Adding a Solar Radiance Function to the Hosek Skylight Model" 10 | 11 | both by 12 | 13 | Lukas Hosek and Alexander Wilkie 14 | Charles University in Prague, Czech Republic 15 | 16 | 17 | Version: 1.4a, February 22nd, 2013 18 | 19 | Version history: 20 | 21 | 1.4a February 22nd, 2013 22 | Removed unnecessary and counter-intuitive solar radius parameters 23 | from the interface of the colourspace sky dome initialisation functions. 24 | 25 | 1.4 February 11th, 2013 26 | Fixed a bug which caused the relative brightness of the solar disc 27 | and the sky dome to be off by a factor of about 6. The sun was too 28 | bright: this affected both normal and alien sun scenarios. The 29 | coefficients of the solar radiance function were changed to fix this. 30 | 31 | 1.3 January 21st, 2013 (not released to the public) 32 | Added support for solar discs that are not exactly the same size as 33 | the terrestrial sun. Also added support for suns with a different 34 | emission spectrum ("Alien World" functionality). 35 | 36 | 1.2a December 18th, 2012 37 | Fixed a mistake and some inaccuracies in the solar radiance function 38 | explanations found in ArHosekSkyModel.h. The actual source code is 39 | unchanged compared to version 1.2. 40 | 41 | 1.2 December 17th, 2012 42 | Native RGB data and a solar radiance function that matches the turbidity 43 | conditions were added. 44 | 45 | 1.1 September 2012 46 | The coefficients of the spectral model are now scaled so that the output 47 | is given in physical units: W / (m^-2 * sr * nm). Also, the output of the 48 | XYZ model is now no longer scaled to the range [0...1]. Instead, it is 49 | the result of a simple conversion from spectral data via the CIE 2 degree 50 | standard observer matching functions. Therefore, after multiplication 51 | with 683 lm / W, the Y channel now corresponds to luminance in lm. 52 | 53 | 1.0 May 11th, 2012 54 | Initial release. 55 | 56 | 57 | Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if 58 | an updated version of this code has been published! 59 | 60 | This archive contains the following files: 61 | 62 | README.txt This file. 63 | 64 | ArHosekSkyModel.h Header file for the reference functions. Their 65 | usage is explained there, and sample code for 66 | calling them is given. 67 | 68 | ArHosekSkyModel.c Implementation of the functions. 69 | 70 | ArHosekSkyModelData_Spectral.h Spectral coefficient data. 71 | ArHosekSkyModelData_CIEXYZ.h CIE XYZ coefficient data. 72 | ArHosekSkyModelData_RGB.h RGB coefficient data. 73 | 74 | Please note that the source files are in C99, and you have to set appropriate 75 | compiler flags for them to work. For example, when compiling this code with 76 | gcc, you have to add the "-std=c99" or "-std=gnu99" flags. -------------------------------------------------------------------------------- /atmosphere/model/hosek/hosek.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/hosek/hosek.h" 31 | 32 | #include 33 | 34 | #include "atmosphere/model/hosek/ArHosekSkyModel.h" 35 | 36 | namespace { 37 | 38 | constexpr SolidAngle kSunSolidAngle = 6.87e-5 * sr; 39 | 40 | // Copied from ArHosekSkyModel.cc. 41 | const double originalSolarRadianceTable[] = { 42 | 7500.0, 43 | 12500.0, 44 | 21127.5, 45 | 26760.5, 46 | 30663.7, 47 | 27825.0, 48 | 25503.8, 49 | 25134.2, 50 | 23212.1, 51 | 21526.7, 52 | 19870.8 53 | }; 54 | 55 | // The Hosek sky radiance was computed uding 'originalSolarRadianceTable' as 56 | // the solar radiance, but we want the result for SolarSpectrum(), used in all 57 | // other models. Thus we correct the result for each wavelength by the ratio 58 | // between the two spectra at this wavelength (including also the Sun solid 59 | // angle to convert radiance to irradiance values). 60 | double SolarSpectrumCorrectionFactor(Wavelength lambda) { 61 | double x = (lambda.to(nm) - 320.0) / 40.0; 62 | if (x < 0.0 || x > 10.0) { 63 | return 1.0; 64 | } 65 | int i = floor(x); 66 | double u = x - i; 67 | SpectralIrradiance new_irradiance = SolarSpectrum()(lambda); 68 | SpectralRadiance old_radiance = (originalSolarRadianceTable[i] * (1.0 - u) + 69 | originalSolarRadianceTable[std::min(i + 1, 10)] * u) * 70 | watt_per_square_meter_per_sr_per_nm; 71 | return (new_irradiance / (old_radiance * kSunSolidAngle))(); 72 | } 73 | 74 | } // anonymous namespace 75 | 76 | Hosek::Hosek(double turbidity) : turbidity_(turbidity) { 77 | for (unsigned int i = 0; i < DimensionlessSpectrum::SIZE; ++i) { 78 | sky_model_state_[i] = NULL; 79 | } 80 | } 81 | 82 | Hosek::~Hosek() { 83 | for (unsigned int i = 0; i < DimensionlessSpectrum::SIZE; ++i) { 84 | if (sky_model_state_[i] != NULL) { 85 | arhosekskymodelstate_free(sky_model_state_[i]); 86 | } 87 | } 88 | } 89 | 90 | IrradianceSpectrum Hosek::GetSunIrradiance(Length altitude, 91 | Angle sun_zenith) const { 92 | MaybeInitSkyModelState(sun_zenith); 93 | IrradianceSpectrum result; 94 | for (unsigned int i = 0; i < result.size(); ++i) { 95 | Wavelength lambda = result.GetSample(i); 96 | if (lambda < 320.0 * nm || lambda > 720.0 * nm) { 97 | // arhosekskymodel_solar_radiance does not work for wavelengths outside 98 | // the 320-720nm range. 99 | result[i] = 0.0 * watt_per_square_meter_per_nm; 100 | continue; 101 | } 102 | double sun_and_sky_radiance = arhosekskymodel_solar_radiance( 103 | sky_model_state_[i], sun_zenith.to(rad), 0.0, lambda.to(nm)); 104 | double sky_radiance = arhosekskymodel_radiance( 105 | sky_model_state_[i], sun_zenith.to(rad), 0.0, lambda.to(nm)); 106 | double sun_radiance = (sun_and_sky_radiance - sky_radiance) * 107 | SolarSpectrumCorrectionFactor(lambda); 108 | result[i] = 109 | sun_radiance * watt_per_square_meter_per_sr_per_nm * kSunSolidAngle; 110 | } 111 | return result; 112 | } 113 | 114 | RadianceSpectrum Hosek::GetSkyRadiance(Length altitude, Angle sun_zenith, 115 | Angle view_zenith, Angle view_sun_azimuth) const { 116 | MaybeInitSkyModelState(sun_zenith); 117 | double gamma = 118 | GetViewSunAngle(sun_zenith, view_zenith, view_sun_azimuth).to(rad); 119 | RadianceSpectrum result; 120 | for (unsigned int i = 0; i < result.size(); ++i) { 121 | Wavelength lambda = result.GetSample(i); 122 | result[i] = arhosekskymodel_radiance(sky_model_state_[i], 123 | view_zenith.to(rad), gamma, lambda.to(nm)) * 124 | SolarSpectrumCorrectionFactor(lambda) * 125 | watt_per_square_meter_per_sr_per_nm; 126 | } 127 | return result; 128 | } 129 | 130 | void Hosek::MaybeInitSkyModelState(Angle sun_zenith) const { 131 | if (sky_model_state_[0] != NULL && sun_zenith == current_sun_zenith_) { 132 | return; 133 | } 134 | if (sky_model_state_[0] != NULL) { 135 | for (unsigned int i = 0; i < DimensionlessSpectrum::SIZE; ++i) { 136 | arhosekskymodelstate_free(sky_model_state_[i]); 137 | } 138 | } 139 | for (unsigned int i = 0; i < DimensionlessSpectrum::SIZE; ++i) { 140 | sky_model_state_[i] = arhosekskymodelstate_alloc_init( 141 | (pi / 2.0 - sun_zenith).to(rad), turbidity_, GroundAlbedo()[i]()); 142 | } 143 | current_sun_zenith_ = sun_zenith; 144 | } 145 | -------------------------------------------------------------------------------- /atmosphere/model/hosek/hosek.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_HOSEK_HOSEK_H_ 31 | #define ATMOSPHERE_MODEL_HOSEK_HOSEK_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "math/angle.h" 35 | #include "physics/units.h" 36 | 37 | struct ArHosekSkyModelState; 38 | 39 | class Hosek : public Atmosphere { 40 | public: 41 | explicit Hosek(double turbidity); 42 | virtual ~Hosek(); 43 | 44 | int GetOriginalNumberOfWavelengths() const override { return 11; } 45 | 46 | IrradianceSpectrum GetSunIrradiance(Length altitude, 47 | Angle sun_zenith) const override; 48 | 49 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 50 | Angle view_zenith, Angle view_sun_azimuth) const override; 51 | 52 | private: 53 | void MaybeInitSkyModelState(Angle sun_zenith) const; 54 | 55 | double turbidity_; 56 | mutable Angle current_sun_zenith_; 57 | mutable ArHosekSkyModelState* sky_model_state_[DimensionlessSpectrum::SIZE]; 58 | }; 59 | 60 | #endif // ATMOSPHERE_MODEL_HOSEK_HOSEK_H_ 61 | -------------------------------------------------------------------------------- /atmosphere/model/libradtran/libradtran.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_LIBRADTRAN_LIBRADTRAN_H_ 31 | #define ATMOSPHERE_MODEL_LIBRADTRAN_LIBRADTRAN_H_ 32 | 33 | #include 34 | 35 | #include "atmosphere/atmosphere.h" 36 | #include "atmosphere/hemispherical_function.h" 37 | #include "atmosphere/measurement/measured_atmospheres.h" 38 | #include "math/angle.h" 39 | #include "math/binary_function.h" 40 | #include "physics/units.h" 41 | 42 | class LibRadtran : public Atmosphere { 43 | public: 44 | enum CacheType { 45 | BINARY_FUNCTION_CACHE, HEMISPHERICAL_FUNCTION_CACHE 46 | }; 47 | 48 | LibRadtran(const std::string& libradtran_uvspec, CacheType cache_type); 49 | 50 | LibRadtran(const std::string& libradtran_uvspec, double mie_angstrom_alpha, 51 | double mie_angstrom_beta, double mie_phase_function_g, bool ground_albedo, 52 | CacheType cache_type); 53 | 54 | // Not implemented. 55 | virtual IrradianceSpectrum GetSunIrradiance(Length altitude, 56 | Angle sun_zenith) const; 57 | 58 | virtual RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 59 | Angle view_zenith, Angle view_sun_azimuth) const; 60 | 61 | virtual RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 62 | Angle sun_azimuth, Angle view_zenith, Angle view_azimuth) const; 63 | 64 | private: 65 | static constexpr int kNumPhi = 120; 66 | static constexpr int kNumTheta = kNumPhi / 4; 67 | static constexpr Angle kDeltaPhi = 2.0 * pi / kNumPhi; 68 | 69 | void MaybeComputeBinaryFunctionCache(Angle sun_zenith) const; 70 | void MaybeComputeHemisphericalFunctionCache(Angle sun_zenith, 71 | Angle sun_azimuth) const; 72 | 73 | std::string libradtran_uvspec_; 74 | CacheType cache_type_; 75 | mutable Angle current_sun_zenith_; 76 | mutable Angle current_sun_azimuth_; 77 | mutable dimensional::BinaryFunction 78 | binary_function_cache_; 79 | mutable HemisphericalFunction hemispherical_function_cache_; 80 | }; 81 | 82 | #endif // ATMOSPHERE_MODEL_LIBRADTRAN_LIBRADTRAN_H_ 83 | -------------------------------------------------------------------------------- /atmosphere/model/nishita/nishita93.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/nishita/nishita93.h" 31 | 32 | #include 33 | 34 | Nishita93::Nishita93() { 35 | // Precomputes the optical length lookup tables. 36 | for (int i = 0; i < kNumSphere; ++i) { 37 | Length r = GetSphereRadius(i); 38 | Length h = r - EarthRadius; 39 | for (int j = 0; j < kNumCylinder; ++j) { 40 | Length c = std::min(GetCylinderRadius(j), r); 41 | Length rmu = sqrt(r * r - c * c); 42 | 43 | Length rayleigh_length = 0.0 * m; 44 | Length mie_length = 0.0 * m; 45 | Number previous_rayleigh_density = exp(-h / RayleighScaleHeight); 46 | Number previous_mie_density = exp(-h / MieScaleHeight); 47 | Length distance_to_previous_sphere = 0.0 * m; 48 | for (int k = i + 1; k < kNumSphere; ++k) { 49 | Length r_k = GetSphereRadius(k); 50 | Length h_k = r_k - EarthRadius; 51 | Length distance_to_sphere = DistanceToSphere(r, rmu, r_k); 52 | Number rayleigh_density = exp(-h_k / RayleighScaleHeight); 53 | Number mie_density = exp(-h_k / MieScaleHeight); 54 | Length segment_length = 55 | distance_to_sphere - distance_to_previous_sphere; 56 | rayleigh_length += (rayleigh_density + previous_rayleigh_density) / 2 * 57 | segment_length; 58 | mie_length += (mie_density + previous_mie_density) / 2 * segment_length; 59 | previous_rayleigh_density = rayleigh_density; 60 | previous_mie_density = mie_density; 61 | distance_to_previous_sphere = distance_to_sphere; 62 | } 63 | rayleigh_optical_length_.Set(i, j, rayleigh_length); 64 | mie_optical_length_.Set(i, j, mie_length); 65 | 66 | rmu = -rmu; 67 | rayleigh_length = 0.0 * m; 68 | mie_length = 0.0 * m; 69 | previous_rayleigh_density = exp(-h / RayleighScaleHeight); 70 | previous_mie_density = exp(-h / MieScaleHeight); 71 | distance_to_previous_sphere = 0.0 * m; 72 | for (int k = i - 1; k > -kNumSphere; --k) { 73 | Length r_k = GetSphereRadius(std::abs(k)); 74 | Length h_k = r_k - EarthRadius; 75 | Length distance_to_sphere = DistanceToSphere(r, rmu, r_k); 76 | if (distance_to_sphere == 0.0 * m) { 77 | continue; 78 | } 79 | Number rayleigh_density = exp(-h_k / RayleighScaleHeight); 80 | Number mie_density = exp(-h_k / MieScaleHeight); 81 | Length segment_length = 82 | distance_to_sphere - distance_to_previous_sphere; 83 | rayleigh_length += (rayleigh_density + previous_rayleigh_density) / 2 * 84 | segment_length; 85 | mie_length += (mie_density + previous_mie_density) / 2 * segment_length; 86 | previous_rayleigh_density = rayleigh_density; 87 | previous_mie_density = mie_density; 88 | distance_to_previous_sphere = distance_to_sphere; 89 | } 90 | rayleigh_opposite_optical_length_.Set(i, j, rayleigh_length); 91 | mie_opposite_optical_length_.Set(i, j, mie_length); 92 | } 93 | } 94 | } 95 | 96 | IrradianceSpectrum Nishita93::GetSunIrradiance(Length altitude, 97 | Angle sun_zenith) const { 98 | Length rayleigh_length; 99 | Length mie_length; 100 | GetOpticalLengths(EarthRadius + altitude, cos(sun_zenith), &rayleigh_length, 101 | &mie_length); 102 | DimensionlessSpectrum optical_depth = RayleighScattering() * rayleigh_length + 103 | MieExtinction() * mie_length; 104 | DimensionlessSpectrum transmittance(exp(-optical_depth)); 105 | return transmittance * SolarSpectrum(); 106 | } 107 | 108 | RadianceSpectrum Nishita93::GetSkyRadiance(Length altitude, Angle sun_zenith, 109 | Angle view_zenith, Angle view_sun_azimuth) const { 110 | Length r = EarthRadius + altitude; 111 | Number mu_s = cos(sun_zenith); 112 | Number mu = cos(view_zenith); 113 | Number nu = 114 | cos(view_sun_azimuth) * sin(view_zenith) * sin(sun_zenith) + mu * mu_s; 115 | Length rmu = r * mu; 116 | Length rmu_s = r * mu_s; 117 | 118 | WavelengthFunction<1, 0, 0, 0, 0> rayleigh_integral(0.0 * m); 119 | WavelengthFunction<1, 0, 0, 0, 0> mie_integral(0.0 * m); 120 | Length rayleigh_length = 0.0 * m; 121 | Length mie_length = 0.0 * m; 122 | Number previous_rayleigh_density = exp(-altitude / RayleighScaleHeight); 123 | Number previous_mie_density = exp(-altitude / MieScaleHeight); 124 | Length distance_to_previous_sphere = 0.0 * m; 125 | DimensionlessSpectrum previous_rayleigh_sample(0.0); 126 | DimensionlessSpectrum previous_mie_sample(0.0); 127 | for (int i = 0; i < kNumSphere; ++i) { 128 | Length r_i = GetSphereRadius(i); 129 | if (r_i <= r) { 130 | continue; 131 | } 132 | Length h_i = r_i - EarthRadius; 133 | Number rayleigh_density = exp(-h_i / RayleighScaleHeight); 134 | Number mie_density = exp(-h_i / MieScaleHeight); 135 | Length distance_to_sphere = DistanceToSphere(r, rmu, r_i); 136 | Length half_segment_length = 137 | (distance_to_sphere - distance_to_previous_sphere) * 0.5; 138 | rayleigh_length += 139 | (rayleigh_density + previous_rayleigh_density) * half_segment_length; 140 | mie_length += (mie_density + previous_mie_density) * half_segment_length; 141 | 142 | Length rayleigh_sun_length; 143 | Length mie_sun_length; 144 | Number mu_s_i = (rmu_s + distance_to_sphere * nu) / r_i; 145 | GetOpticalLengths(r_i, mu_s_i, &rayleigh_sun_length, &mie_sun_length); 146 | 147 | DimensionlessSpectrum optical_depth = 148 | RayleighScattering() * (rayleigh_length + rayleigh_sun_length) + 149 | MieExtinction() * (mie_length + mie_sun_length); 150 | DimensionlessSpectrum transmittance(exp(-optical_depth)); 151 | DimensionlessSpectrum rayleigh_sample(transmittance * rayleigh_density); 152 | DimensionlessSpectrum mie_sample(transmittance * mie_density); 153 | rayleigh_integral += 154 | (rayleigh_sample + previous_rayleigh_sample) * half_segment_length; 155 | mie_integral += (mie_sample + previous_mie_sample) * half_segment_length; 156 | 157 | previous_rayleigh_density = rayleigh_density; 158 | previous_mie_density = mie_density; 159 | distance_to_previous_sphere = distance_to_sphere; 160 | previous_rayleigh_sample = rayleigh_sample; 161 | previous_mie_sample = mie_sample; 162 | } 163 | 164 | InverseSolidAngle rayleigh_phase = RayleighPhaseFunction(nu); 165 | InverseSolidAngle mie_phase = MiePhaseFunction(nu); 166 | return (rayleigh_integral * RayleighScattering() * rayleigh_phase + 167 | mie_integral * MieScattering() * mie_phase) * SolarSpectrum(); 168 | } 169 | 170 | void Nishita93::GetOpticalLengths(Length r, Number mu, Length* rayleigh_length, 171 | Length* mie_length) const { 172 | constexpr Number a = 173 | exp(-(AtmosphereRadius - EarthRadius) / RayleighScaleHeight) - 1.0; 174 | Number x = (exp(-(r - EarthRadius) / RayleighScaleHeight) - 1.0) / a; 175 | Number y = r * sqrt(1.0 - mu * mu) / AtmosphereRadius; 176 | x = 0.5 / kNumSphere + (kNumSphere - 1.0) / kNumSphere * x; 177 | y = 0.5 / kNumCylinder + (kNumCylinder - 1.0) / kNumCylinder * y; 178 | if (mu >= 0.0) { 179 | *rayleigh_length = rayleigh_optical_length_(x(), y()); 180 | *mie_length = mie_optical_length_(x(), y()); 181 | } else { 182 | *rayleigh_length = rayleigh_opposite_optical_length_(x(), y()); 183 | *mie_length = mie_opposite_optical_length_(x(), y()); 184 | } 185 | } 186 | 187 | Length Nishita93::GetSphereRadius(int sphere_index) { 188 | constexpr Number a = 189 | exp(-(AtmosphereRadius - EarthRadius) / RayleighScaleHeight) - 1.0; 190 | double x = sphere_index / static_cast(kNumSphere - 1); 191 | return EarthRadius - RayleighScaleHeight * log(a * x + 1.0); 192 | } 193 | 194 | Length Nishita93::GetCylinderRadius(int cylinder_index) { 195 | double x = cylinder_index / static_cast(kNumCylinder - 1); 196 | return AtmosphereRadius * x; 197 | } 198 | 199 | Length Nishita93::DistanceToSphere(Length r, Length rmu, Length sphere_radius) { 200 | Area delta_sq = sphere_radius * sphere_radius - r * r + rmu * rmu; 201 | return delta_sq < 0.0 * m2 ? 0.0 * m : 202 | (r < sphere_radius ? -rmu + sqrt(delta_sq) : -rmu - sqrt(delta_sq)); 203 | } 204 | -------------------------------------------------------------------------------- /atmosphere/model/nishita/nishita93.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_NISHITA_NISHITA93_H_ 31 | #define ATMOSPHERE_MODEL_NISHITA_NISHITA93_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "math/angle.h" 35 | #include "math/binary_function.h" 36 | #include "physics/units.h" 37 | 38 | class Nishita93 : public Atmosphere { 39 | public: 40 | Nishita93(); 41 | 42 | int GetOriginalNumberOfWavelengths() const override { return 3; } 43 | 44 | IrradianceSpectrum GetSunIrradiance(Length altitude, 45 | Angle sun_zenith) const override; 46 | 47 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 48 | Angle view_zenith, Angle view_sun_azimuth) const override; 49 | 50 | protected: 51 | // Returns the optical lengths for rayleigh and mie particles between a point 52 | // at radius r and the top of the atmosphere in a direction whose angle with 53 | // the local vertical is acos(mu). This is done by using the precomputed 54 | // optical length lookup tables. 55 | void GetOpticalLengths(Length r, Number mu, Length* rayleigh_length, 56 | Length* mie_length) const; 57 | 58 | // Computes the sphere radius noted r_i in Nishita93. 59 | static Length GetSphereRadius(int sphere_index); 60 | 61 | // Computes the cylinder radius noted C_j in Nishita93. 62 | static Length GetCylinderRadius(int cylinder_index); 63 | 64 | // Returns the distance from a point at radius r to the sphere of radius 65 | // sphere_radius in a direction whose angle with the local vertical is 66 | // acos(rmu / r), or 0 if there is no intersection. 67 | static Length DistanceToSphere(Length r, Length rmu, Length sphere_radius); 68 | 69 | // Number of virtual spheres and cylinders for the optical length lookup table 70 | // described in Section 4.3.4 and Fig. 4 of Nishita93. 71 | static constexpr int kNumSphere = 64; 72 | static constexpr int kNumCylinder = 64; 73 | 74 | // Optical lengths between a point of the intersection circle between a sphere 75 | // and a cylinder, and the Sun. The cylinder axis being the Sun direction. 76 | dimensional::BinaryFunction 77 | rayleigh_optical_length_; 78 | dimensional::BinaryFunction 79 | mie_optical_length_; 80 | // Same, with the Sun in the opposite direction of the cylinder axis. 81 | dimensional::BinaryFunction 82 | rayleigh_opposite_optical_length_; 83 | dimensional::BinaryFunction 84 | mie_opposite_optical_length_; 85 | }; 86 | 87 | #endif // ATMOSPHERE_MODEL_NISHITA_NISHITA93_H_ 88 | -------------------------------------------------------------------------------- /atmosphere/model/nishita/nishita96.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_NISHITA_NISHITA96_H_ 31 | #define ATMOSPHERE_MODEL_NISHITA_NISHITA96_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "atmosphere/model/nishita/nishita93.h" 35 | #include "math/angle.h" 36 | #include "math/ternary_function.h" 37 | #include "math/vector.h" 38 | #include "physics/units.h" 39 | 40 | class Nishita96 : public Nishita93 { 41 | public: 42 | enum ScatteringType { 43 | SINGLE_SCATTERING_ONLY, DOUBLE_SCATTERING_ONLY, ALL_ORDERS 44 | }; 45 | 46 | explicit Nishita96(ScatteringType scattering_type); 47 | 48 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 49 | Angle view_zenith, Angle view_sun_azimuth) const override; 50 | 51 | private: 52 | static constexpr int kNumSteps = 33; 53 | 54 | typedef dimensional::TernaryFunction> SingleScatteringFunction; 56 | typedef dimensional::Vector3 Position; 57 | typedef dimensional::Vector3 Direction; 58 | 59 | class SingleScatteringTable { 60 | public: 61 | void Init(Angle sun_zenith, Angle view_zenith); 62 | 63 | WavelengthFunction<0, 0, -1, 0, 0> GetSingleScattering( 64 | const Position& p) const; 65 | 66 | void GetPosition(const dimensional::vec3& u, Position* p) const; 67 | void GetU(const Position& p, dimensional::vec3* u) const; 68 | 69 | Angle view_zenith_; 70 | Number cos_view_zenith_; 71 | Number sin_view_zenith_; 72 | SingleScatteringFunction value_; 73 | }; 74 | 75 | void MaybePrecomputeSingleScatteringTables(Angle sun_zenith) const; 76 | 77 | void PreComputeSingleScatteringTable(Angle sun_zenith, Angle view_zenith, 78 | SingleScatteringTable* output) const; 79 | 80 | void PreComputeSingleScattering(const Position& p, const Direction& d, 81 | Length step, const Direction& sun_dir, int i, int j, 82 | SingleScatteringFunction* output) const; 83 | 84 | void GetTransmittance(const Position& p, const Direction& d, 85 | DimensionlessSpectrum* transmittance) const; 86 | 87 | // d must be normalized. 88 | static bool IntersectsGround(const Position& p, const Direction& d); 89 | 90 | // Returns the distance from a point at radius r to the sphere of radius 91 | // sphere_radius in a direction whose angle with the local vertical is 92 | // acos(rmu / r), or 0 if there is no intersection. 93 | static Length DistanceToSphere(Length r, Length rmu, Length sphere_radius); 94 | 95 | // p must be outside the atmosphere and d must be normalized. 96 | static Length DistanceToTopOfAtmosphere(const Position& p, 97 | const Direction& d); 98 | 99 | // p must be inside the atmosphere and d must be normalized. 100 | static Length DistanceToGroundOrTopOfAtmosphere(const Position& p, 101 | const Direction& d); 102 | 103 | ScatteringType scattering_type_; 104 | mutable Angle current_sun_zenith_; 105 | mutable dimensional::Vector3 sample_directions_[8]; 106 | mutable SingleScatteringTable sample_single_scattering_[8]; 107 | }; 108 | 109 | #endif // ATMOSPHERE_MODEL_NISHITA_NISHITA96_H_ 110 | -------------------------------------------------------------------------------- /atmosphere/model/oneal/oneal.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /* 32 | Adapted from Sean O'Neil "Accurate Atmospheric Scattering", GPU Gems 2, 2004. 33 | More precisely from the SkyFromAtmosphere.vert file from the GPU Gems 2 CD. 34 | 35 | Original header: 36 | // Atmospheric scattering vertex shader 37 | // 38 | // Author: Sean O'Neil 39 | // 40 | // Copyright (c) 2004 Sean O'Neil 41 | // 42 | */ 43 | 44 | #include "atmosphere/model/oneal/oneal.h" 45 | 46 | #include "math/vector.h" 47 | 48 | typedef dimensional::Vector3 Position; 49 | typedef dimensional::Vector3 Vector; 50 | typedef dimensional::Vector3 Direction; 51 | 52 | namespace { 53 | 54 | // Returns the distance from a point at radius r to the sphere of radius 55 | // sphere_radius in a direction whose angle with the local vertical is 56 | // acos(rmu / r), or 0 if there is no intersection. 57 | Length DistanceToSphere(Length r, Length rmu, Length sphere_radius) { 58 | Area delta_sq = sphere_radius * sphere_radius - r * r + rmu * rmu; 59 | return delta_sq < 0.0 * m2 ? 0.0 * m : 60 | (r < sphere_radius ? -rmu + sqrt(delta_sq) : -rmu - sqrt(delta_sq)); 61 | } 62 | 63 | // Scale function based on "An Approximation to the Chapman Grazing-Incidence 64 | // Function for Atmospheric Scattering", C. Schüler, GPU Pro 3, 2012. We use 65 | // this to replace the original function from O'Neal, which is specific to the 66 | // atmospheric parameters he used. 67 | Length Scale(Length H, Number mu) { 68 | Number c = sqrt(EarthRadius / H); 69 | return H * c / (c * mu + 1.0); 70 | } 71 | 72 | } // namespace 73 | 74 | ONeal::ONeal() { 75 | } 76 | 77 | IrradianceSpectrum ONeal::GetSunIrradiance(Length altitude, 78 | Angle sun_zenith) const { 79 | Number f_rayleigh_depth = exp(-altitude / RayleighScaleHeight); 80 | Number f_mie_depth = exp(-altitude / MieScaleHeight); 81 | Number f_light_angle = cos(sun_zenith); 82 | Length f_rayleigh_scatter = 83 | f_rayleigh_depth * Scale(RayleighScaleHeight, f_light_angle); 84 | Length f_mie_scatter = f_mie_depth * Scale(MieScaleHeight, f_light_angle); 85 | DimensionlessSpectrum attenuate = exp(-(MieExtinction() * f_mie_scatter + 86 | RayleighScattering() * f_rayleigh_scatter)); 87 | return attenuate * SolarSpectrum(); 88 | } 89 | 90 | RadianceSpectrum ONeal::GetSkyRadiance(Length altitude, Angle sun_zenith, 91 | Angle view_zenith, Angle view_sun_azimuth) const { 92 | Length f_inner_radius = EarthRadius; 93 | Length f_camera_height = f_inner_radius + altitude; 94 | Position v3_camera_pos(0.0 * m, 0.0 * m, f_camera_height); 95 | Direction v3_light_pos(cos(view_sun_azimuth) * sin(sun_zenith), 96 | sin(view_sun_azimuth) * sin(sun_zenith), cos(sun_zenith)); 97 | 98 | // Get the ray from the camera, and its length. 99 | Direction v3_ray(sin(view_zenith), 0.0, cos(view_zenith)); 100 | Length f_far = DistanceToSphere( 101 | f_camera_height, f_camera_height * cos(view_zenith), AtmosphereRadius); 102 | 103 | // Calculate the ray's starting position, and calculate its scattering offset. 104 | Position v3_start = v3_camera_pos; 105 | Length f_height = length(v3_start); 106 | Number f_rayleigh_depth = 107 | exp((f_inner_radius - f_height) / RayleighScaleHeight); 108 | Number f_mie_depth = exp((f_inner_radius - f_height) / MieScaleHeight); 109 | Number f_start_angle = dot(v3_ray, v3_start) / f_height; 110 | Length f_rayleigh_start_offset = 111 | f_rayleigh_depth * Scale(RayleighScaleHeight, f_start_angle); 112 | Length f_mie_start_offset = 113 | f_mie_depth * Scale(MieScaleHeight, f_start_angle); 114 | 115 | // Note: the original implementation uses only 2 samples. 116 | const int kNumSamples = 4; 117 | 118 | // Initialize the scattering loop variables. 119 | Length f_sample_length = f_far / kNumSamples; 120 | Vector v3_sample_ray = v3_ray * f_sample_length; 121 | Position v3_sample_point = v3_start + v3_sample_ray * Number(0.5); 122 | 123 | // Now loop through the sample rays. 124 | WavelengthFunction<1, 0, 0, 0, 0> front_color(0.0 * m); 125 | WavelengthFunction<1, 0, 0, 0, 0> front_secondary_color(0.0 * m); 126 | for (int i = 0; i < kNumSamples; ++i) { 127 | f_height = length(v3_sample_point); 128 | f_rayleigh_depth = exp((f_inner_radius - f_height) / RayleighScaleHeight); 129 | f_mie_depth = exp((f_inner_radius - f_height) / MieScaleHeight); 130 | Number f_light_angle = dot(v3_light_pos, v3_sample_point) / f_height; 131 | Number f_camera_angle = dot(v3_ray, v3_sample_point) / f_height; 132 | Length f_rayleigh_scatter = f_rayleigh_start_offset + f_rayleigh_depth * ( 133 | Scale(RayleighScaleHeight, f_light_angle) - 134 | Scale(RayleighScaleHeight, f_camera_angle)); 135 | Length f_mie_scatter = f_mie_start_offset + f_mie_depth * ( 136 | Scale(MieScaleHeight, f_light_angle) - 137 | Scale(MieScaleHeight, f_camera_angle)); 138 | DimensionlessSpectrum attenuate = exp(-(MieExtinction() * f_mie_scatter + 139 | RayleighScattering() * f_rayleigh_scatter)); 140 | front_color = front_color + 141 | attenuate * (f_rayleigh_depth * f_sample_length); 142 | front_secondary_color = front_secondary_color + 143 | attenuate * (f_mie_depth * f_sample_length); 144 | v3_sample_point = v3_sample_point + v3_sample_ray; 145 | } 146 | 147 | Number nu = dot(v3_ray, v3_light_pos); 148 | InverseSolidAngle rayleigh_phase = RayleighPhaseFunction(nu); 149 | InverseSolidAngle mie_phase = MiePhaseFunction(nu); 150 | return (front_color * RayleighScattering() * rayleigh_phase + 151 | front_secondary_color * MieScattering() * mie_phase) * SolarSpectrum(); 152 | } 153 | -------------------------------------------------------------------------------- /atmosphere/model/oneal/oneal.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_ONEAL_ONEAL_H_ 31 | #define ATMOSPHERE_MODEL_ONEAL_ONEAL_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "math/angle.h" 35 | #include "physics/units.h" 36 | 37 | class ONeal : public Atmosphere { 38 | public: 39 | ONeal(); 40 | 41 | int GetOriginalNumberOfWavelengths() const override { return 3; } 42 | 43 | IrradianceSpectrum GetSunIrradiance(Length altitude, 44 | Angle sun_zenith) const override; 45 | 46 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 47 | Angle view_zenith, Angle view_sun_azimuth) const override; 48 | }; 49 | 50 | #endif // ATMOSPHERE_MODEL_ONEAL_ONEAL_H_ 51 | -------------------------------------------------------------------------------- /atmosphere/model/polradtran/polradtran.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/polradtran/polradtran.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "util/progress_bar.h" 38 | 39 | constexpr Angle PolRadtran::kDeltaPhi; 40 | 41 | PolRadtran::PolRadtran(const std::string& libradtran_uvspec, 42 | const std::string& libradtran_data, bool polarization) 43 | : libradtran_uvspec_(libradtran_uvspec), libradtran_data_(libradtran_data), 44 | polarization_(polarization) { 45 | // Source: solar spectrum. 46 | IrradianceSpectrum solar = SolarSpectrum(); 47 | std::ofstream source("output/libradtran/solar_spectrum.txt"); 48 | for (unsigned int i = 0; i < solar.size(); ++i) { 49 | source << solar.GetSample(i).to(nm) << " " 50 | << solar[i].to(watt_per_square_meter_per_nm) << std::endl; 51 | } 52 | source.close(); 53 | 54 | // Wavelengths. 55 | std::ofstream grid("output/libradtran/wavelength_grid.txt"); 56 | for (unsigned int i = 0; i < solar.size(); ++i) { 57 | grid << solar.GetSample(i).to(nm) << std::endl; 58 | } 59 | grid.close(); 60 | 61 | // libRadtran input model file. 62 | std::ofstream model("output/libradtran/model.txt"); 63 | model << "data_files_path " << libradtran_data << "\n"; 64 | model << "\n#source irradiance\n"; 65 | model << "source solar output/libradtran/solar_spectrum.txt per_nm\n"; 66 | model << "wavelength " << solar.GetSample(0).to(nm) << " " 67 | << solar.GetSample(solar.size() - 1).to(nm) << std::endl; 68 | model << "wavelength_grid_file output/libradtran/wavelength_grid.txt\n"; 69 | model << "\n#molecular properties\n"; 70 | model << "mol_abs_param crs\n"; 71 | model << "\n#aerosol properties\n"; 72 | model << "aerosol_default\n"; 73 | model << "aerosol_species_file continental_clean\n"; 74 | model << "\n#ground properties\n"; 75 | model << "albedo 0.1\n"; 76 | model << "\n#solver and output options\n"; 77 | model << "rte_solver polradtran\n"; 78 | model << "polradtran nstokes " << (polarization ? 3 : 1) << "\n"; 79 | model << "output_process per_nm\n"; 80 | model << "output_user lambda uu\n"; 81 | model << "quiet\n"; 82 | model.close(); 83 | } 84 | 85 | IrradianceSpectrum PolRadtran::GetSunIrradiance(Length altitude, 86 | Angle sun_zenith) const { 87 | IrradianceSpectrum result(0.0 * watt_per_square_meter_per_nm); 88 | return result; 89 | } 90 | 91 | RadianceSpectrum PolRadtran::GetSkyRadiance(Length altitude, Angle sun_zenith, 92 | Angle view_zenith, Angle view_sun_azimuth) const { 93 | assert(altitude == 0.0 * m); 94 | MaybeComputeSkyDome(sun_zenith); 95 | if (view_sun_azimuth < 0.0 * deg) { 96 | view_sun_azimuth = -view_sun_azimuth; 97 | } 98 | while (view_sun_azimuth > 2.0 * pi) { 99 | view_sun_azimuth = view_sun_azimuth - 2.0 * pi; 100 | } 101 | if (view_sun_azimuth > pi) { 102 | view_sun_azimuth = 2.0 * pi - view_sun_azimuth; 103 | } 104 | Number u = view_zenith / (kNumTheta * kDeltaPhi); 105 | Number v = view_sun_azimuth / (kNumPhi / 2 * kDeltaPhi); 106 | return sky_dome_(u(), v()); 107 | } 108 | 109 | void PolRadtran::MaybeComputeSkyDome(Angle sun_zenith) const { 110 | if (current_sun_zenith_ == sun_zenith) { 111 | return; 112 | } 113 | current_sun_zenith_ = sun_zenith; 114 | 115 | std::stringstream name; 116 | name << "output/cache/polradtran/sky_dome_" << sun_zenith.to(deg) << "_" 117 | << (polarization_ ? "vector.dat" : "scalar.dat"); 118 | std::ifstream f; 119 | f.open(name.str()); 120 | if (f.good()) { 121 | f.close(); 122 | sky_dome_.Load(name.str()); 123 | return; 124 | } 125 | 126 | const auto& spectrum = sky_dome_.Get(0, 0); 127 | ProgressBar progress_bar(kNumTheta); 128 | for (int i = 0; i < kNumTheta; ++i) { 129 | Angle view_zenith = (i + 0.5) * kDeltaPhi; 130 | std::ofstream input("output/libradtran/input.txt"); 131 | input << "include output/libradtran/model.txt" << std::endl; 132 | input << "sza " << sun_zenith.to(deg) << std::endl; 133 | input << "phi0 0.0" << std::endl; 134 | input << "umu " << -cos(view_zenith)(); 135 | input << std::endl << "phi"; 136 | for (int j = 0; j < kNumPhi / 2; ++j) { 137 | Angle view_azimuth = (j + 0.5) * kDeltaPhi; 138 | input << " " << view_azimuth.to(deg); 139 | } 140 | input << std::endl; 141 | input.close(); 142 | 143 | const std::string cmd = 144 | libradtran_uvspec_ + " -i output/libradtran/input.txt"; 145 | FILE* pipe = popen(cmd.c_str(), "r"); 146 | if (!pipe) { 147 | return; 148 | } 149 | char buffer[256]; 150 | std::string output = ""; 151 | while (!feof(pipe)) { 152 | if (fgets(buffer, 256, pipe) != NULL) { 153 | output += buffer; 154 | } 155 | } 156 | pclose(pipe); 157 | 158 | std::stringstream string_stream(output); 159 | for (unsigned int j = 0; j < spectrum.size(); ++j) { 160 | double lambda; 161 | double radiance; 162 | double ignored; 163 | string_stream >> lambda; 164 | assert(lambda == spectrum.GetSample(j).to(nm)); 165 | for (int k = 0; k < kNumPhi / 2 + (polarization_ ? 6 : 2); ++k) { 166 | string_stream >> ignored; 167 | } 168 | std::string comment; 169 | std::getline(string_stream, comment); 170 | std::getline(string_stream, comment); 171 | string_stream >> ignored; 172 | string_stream >> ignored; 173 | for (int k = 0; k < kNumPhi / 2; ++k) { 174 | string_stream >> radiance; 175 | sky_dome_.Get(i, k)[j] = radiance * watt_per_square_meter_per_sr_per_nm; 176 | } 177 | if (polarization_) { 178 | std::getline(string_stream, comment); 179 | std::getline(string_stream, comment); 180 | for (int k = 0; k < kNumPhi / 2 + 2; ++k) { 181 | string_stream >> ignored; 182 | } 183 | std::getline(string_stream, comment); 184 | std::getline(string_stream, comment); 185 | for (int k = 0; k < kNumPhi / 2 + 2; ++k) { 186 | string_stream >> ignored; 187 | } 188 | } 189 | } 190 | progress_bar.Increment(i); 191 | } 192 | sky_dome_.Save(name.str()); 193 | } 194 | -------------------------------------------------------------------------------- /atmosphere/model/polradtran/polradtran.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_POLRADTRAN_POLRADTRAN_H_ 31 | #define ATMOSPHERE_MODEL_POLRADTRAN_POLRADTRAN_H_ 32 | 33 | #include 34 | 35 | #include "atmosphere/atmosphere.h" 36 | #include "math/angle.h" 37 | #include "math/binary_function.h" 38 | #include "physics/units.h" 39 | 40 | // WARNING: this model does not use the common atmospheric parameters used in 41 | // all other models. It is only used to compare the sky radiance distribution 42 | // simulation results with or without taking polarization into account. 43 | class PolRadtran : public Atmosphere { 44 | public: 45 | PolRadtran(const std::string& libradtran_uvspec, 46 | const std::string& libradtran_data, bool polarization); 47 | 48 | // Not implemented. 49 | virtual IrradianceSpectrum GetSunIrradiance(Length altitude, 50 | Angle sun_zenith) const; 51 | 52 | virtual RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 53 | Angle view_zenith, Angle view_sun_azimuth) const; 54 | 55 | private: 56 | static constexpr int kNumPhi = 120; 57 | static constexpr int kNumTheta = kNumPhi / 4; 58 | static constexpr Angle kDeltaPhi = 2.0 * pi / kNumPhi; 59 | 60 | void MaybeComputeSkyDome(Angle sun_zenith) const; 61 | 62 | std::string libradtran_uvspec_; 63 | std::string libradtran_data_; 64 | bool polarization_; 65 | mutable Angle current_sun_zenith_; 66 | mutable dimensional::BinaryFunction 67 | sky_dome_; 68 | }; 69 | 70 | #endif // ATMOSPHERE_MODEL_POLRADTRAN_POLRADTRAN_H_ 71 | -------------------------------------------------------------------------------- /atmosphere/model/preetham/preetham.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "atmosphere/model/preetham/preetham.h" 31 | 32 | #include 33 | 34 | #include "physics/cie.h" 35 | 36 | namespace { 37 | 38 | class PerezFunction { 39 | public: 40 | PerezFunction(Number a, Number b, Number c, Number d, Number e) 41 | : a_(a), b_(b), c_(c), d_(d), e_(e) {} 42 | 43 | Number operator()(Angle sun_zenith, Angle view_zenith, Angle view_sun) const { 44 | return (*this)(view_zenith, view_sun) / (*this)(0.0 * rad, sun_zenith); 45 | } 46 | 47 | private: 48 | Number operator()(Angle view_zenith, Angle view_sun) const { 49 | return (1.0 + a_ * exp(b_ / cos(view_zenith))) * 50 | (1.0 + c_ * exp(d_ * view_sun.to(rad)) + 51 | e_ * cos(view_sun) * cos(view_sun)); 52 | } 53 | 54 | const Number a_; 55 | const Number b_; 56 | const Number c_; 57 | const Number d_; 58 | const Number e_; 59 | }; 60 | 61 | struct Tables { 62 | std::vector ozone_samples; 63 | std::vector vapor_samples; 64 | std::vector gas_samples; 65 | 66 | Tables() { 67 | // Values from Table 2 in Preetham 1999. 68 | Add(0.0, 0.0, 0.0); 69 | Add(0.3, 0.0, 0.0); 70 | Add(0.6, 0.0, 0.0); 71 | Add(0.9, 0.0, 0.0); 72 | Add(1.4, 0.0, 0.0); 73 | Add(2.1, 0.0, 0.0); 74 | Add(3.0, 0.0, 0.0); 75 | Add(4.0, 0.0, 0.0); 76 | Add(4.8, 0.0, 0.0); 77 | Add(6.3, 0.0, 0.0); 78 | Add(7.5, 0.0, 0.0); 79 | Add(8.5, 0.0, 0.0); 80 | Add(10.3, 0.0, 0.0); 81 | Add(12.0, 0.0, 0.0); 82 | Add(12.0, 0.0, 0.0); 83 | Add(11.5, 0.0, 0.0); 84 | Add(12.5, 0.0, 0.0); 85 | Add(12.0, 0.0, 0.0); 86 | Add(10.5, 0.0, 0.0); 87 | Add(9.0, 0.0, 0.0); 88 | Add(7.9, 0.0, 0.0); 89 | Add(6.7, 0.0, 0.0); 90 | Add(5.7, 0.0, 0.0); 91 | Add(4.8, 0.0, 0.0); 92 | Add(3.6, 0.0, 0.0); 93 | Add(2.8, 1.6, 0.0); 94 | Add(2.3, 2.4, 0.0); 95 | Add(1.8, 1.25, 0.0); 96 | Add(1.4, 100.0, 0.0); 97 | Add(1.1, 87.0, 0.0); 98 | Add(1.0, 6.1, 0.0); 99 | Add(0.9, 0.1, 0.0); 100 | Add(0.7, 0.001, 3.0); 101 | Add(0.4, 0.001, 0.21); 102 | Add(0.0, 0.06, 0.0); 103 | Add(0.0, 0.0, 0.0); 104 | } 105 | 106 | private: 107 | void Add(double ozone_sample, double vapor_sample, double gas_sample) { 108 | ozone_samples.push_back(ozone_sample / m); 109 | vapor_samples.push_back(vapor_sample / m); 110 | gas_samples.push_back(gas_sample); 111 | } 112 | }; 113 | 114 | const Tables tables = Tables(); 115 | const ScatteringSpectrum k_ozone(440.0 * nm, 790.0 * nm, tables.ozone_samples); 116 | const ScatteringSpectrum k_vapor(440.0 * nm, 790.0 * nm, tables.vapor_samples); 117 | const DimensionlessSpectrum k_gas(440.0 * nm, 790.0 * nm, tables.gas_samples); 118 | 119 | } // anonymous namespace 120 | 121 | Preetham::Preetham(double turbidity) : turbidity_(turbidity) {} 122 | 123 | IrradianceSpectrum Preetham::GetSunIrradiance(Length altitude, 124 | Angle sun_zenith) const { 125 | assert(altitude == 0.0 * m); 126 | IrradianceSpectrum result = SolarSpectrum(); 127 | // Formulas from Appendix 1 in Preetham 1999. 128 | Number air_mass = 129 | 1.0 / (cos(sun_zenith) + 0.15 * pow(93.885 - sun_zenith.to(deg), -1.253)); 130 | for (unsigned int i = 0; i < result.size(); ++i) { 131 | Wavelength lambda = result.GetSample(i); 132 | constexpr Wavelength lambda0 = 1000.0 * nm; 133 | // Transmittance due to Rayleigh scattering. 134 | Number rayleigh_transmittance = 135 | exp(-0.008735 * air_mass * pow(lambda / lambda0, -4.08)); 136 | // Transmittance due to Mie scattering. 137 | double beta = 0.04608 * turbidity_ - 0.04586; 138 | constexpr double alpha = 1.3; 139 | Number mie_transmittance = 140 | exp(-beta * air_mass * pow(lambda / lambda0, -alpha)); 141 | // Transmittance of the ozone layer. 142 | constexpr Length l = 0.0035 * m; 143 | Number ozone_transmittance = exp(-air_mass * l * k_ozone[i]); 144 | // Transmittance of the other gases. 145 | Number gas_transmittance = exp(-1.41 * air_mass * k_gas[i] / 146 | pow(1.0 + 118.93 * k_gas[i] * air_mass, 0.45)); 147 | // Transmittance of the water vapor. 148 | constexpr Length w = 0.02 * m; 149 | Number vapor_transmittance = exp(-0.2385 * k_vapor[i] * w * air_mass / 150 | pow(1.0 + 20.07 * k_vapor[i] * w * air_mass, 0.45)); 151 | // The ground irradiance is the extraterrestrial solar irradiance times the 152 | // total transmittance. 153 | result[i] = result[i] * rayleigh_transmittance * mie_transmittance * 154 | ozone_transmittance * gas_transmittance * vapor_transmittance; 155 | } 156 | return result; 157 | } 158 | 159 | RadianceSpectrum Preetham::GetSkyRadiance(Length altitude, Angle sun_zenith, 160 | Angle view_zenith, Angle view_sun_azimuth) const { 161 | assert(altitude == 0.0 * m); 162 | // Values and formulas from Appendix 2 of Preetham 1999. 163 | PerezFunction Y_function( 164 | 0.1787 * turbidity_ - 1.4630, 165 | -0.3554 * turbidity_ + 0.4275, 166 | -0.0227 * turbidity_ + 5.3251, 167 | 0.1206 * turbidity_ - 2.5771, 168 | -0.0670 * turbidity_ + 0.3703); 169 | PerezFunction x_function( 170 | -0.0193 * turbidity_ - 0.2592, 171 | -0.0665 * turbidity_ + 0.0008, 172 | -0.0004 * turbidity_ + 0.2125, 173 | -0.0641 * turbidity_ - 0.8989, 174 | -0.0033 * turbidity_ + 0.0452); 175 | PerezFunction y_function( 176 | -0.0167 * turbidity_ - 0.2608, 177 | -0.0950 * turbidity_ + 0.0092, 178 | -0.0079 * turbidity_ + 0.2102, 179 | -0.0441 * turbidity_ - 1.6537, 180 | -0.0109 * turbidity_ + 0.0529); 181 | double t = sun_zenith.to(rad); 182 | double t2 = t * t; 183 | double t3 = t * t2; 184 | double T = turbidity_; 185 | double T2 = T * T; 186 | // Absolute zenith luminance and zenith chromaticity values: 187 | double khi = (4.0 / 9.0 - T / 120.0) * (PI - 2.0 * t); 188 | Luminance Y_zenith = 189 | ((4.0453 * T - 4.9710) * tan(khi) - 0.2155 * T + 2.4192) * kcd / m2; 190 | double x_zenith = 191 | (+0.00166 * t3 - 0.00375 * t2 + 0.00209 * t + 0.00000) * T2 + 192 | (-0.02903 * t3 + 0.06377 * t2 - 0.03202 * t + 0.00394) * T + 193 | (+0.11693 * t3 - 0.21196 * t2 + 0.06052 * t + 0.25886); 194 | double y_zenith = 195 | (+0.00275 * t3 - 0.00610 * t2 + 0.00317 * t + 0.00000) * T2 + 196 | (-0.04214 * t3 + 0.08970 * t2 - 0.04153 * t + 0.00516) * T + 197 | (+0.15346 * t3 - 0.26756 * t2 + 0.06670 * t + 0.26688); 198 | // Absolute luminance and chromaticity values in the view direction: 199 | Angle view_sun = GetViewSunAngle(sun_zenith, view_zenith, view_sun_azimuth); 200 | Luminance Y = Y_zenith * Y_function(sun_zenith, view_zenith, view_sun); 201 | Number x = x_zenith * x_function(sun_zenith, view_zenith, view_sun); 202 | Number y = y_zenith * y_function(sun_zenith, view_zenith, view_sun); 203 | // Relative spectral power distribution (unitless). 204 | // Values and formulas from Appendix 6 of Preetham 1999. 205 | Number M1 = (-1.3515 - 1.7703 * x + 5.9114 * y) / 206 | (0.0241 + 0.2562 * x - 0.7341 * y); 207 | Number M2 = (0.0300 - 31.4424 * x + 30.0717 * y) / 208 | (0.0241 + 0.2562 * x - 0.7341 * y); 209 | DimensionlessSpectrum S = 210 | S0_function() + S1_function() * M1 + S2_function() * M2; 211 | // The absolute spectral power distribution L (in W/m^2/sr/nm) we want to 212 | // return is the relative spectral power distribution S times some unknown 213 | // scalar k (also in W/m^2/sr/nm): L = k*S. In order to compute k, we use the 214 | // relation between the spectral radiance L and the luminance Y, namely: 215 | // 216 | // Y = 683.0 lm / W * integral of y_bar(lambda)*L(lambda) dlambda 217 | // 218 | // where y_bar is the CIE photoptic luminosity function (see 219 | // https://en.wikipedia.org/wiki/Luminosity_function#Details). Substituting 220 | // L = k*S = k*(S0 + S1 * M1 + S2 * M2) in the above equation, and noting: 221 | // 222 | static const auto Y_S0 = 223 | MaxLuminousEfficacy * Integral(S0_function() * cie_y_bar_function()); 224 | static const auto Y_S1 = 225 | MaxLuminousEfficacy * Integral(S1_function() * cie_y_bar_function()); 226 | static const auto Y_S2 = 227 | MaxLuminousEfficacy * Integral(S2_function() * cie_y_bar_function()); 228 | // 229 | // we get: 230 | // 231 | SpectralRadiance k = Y / (Y_S0 + Y_S1 * M1 + Y_S2 * M2); 232 | return S * k; 233 | } 234 | -------------------------------------------------------------------------------- /atmosphere/model/preetham/preetham.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef ATMOSPHERE_MODEL_PREETHAM_PREETHAM_H_ 31 | #define ATMOSPHERE_MODEL_PREETHAM_PREETHAM_H_ 32 | 33 | #include "atmosphere/atmosphere.h" 34 | #include "math/angle.h" 35 | #include "physics/units.h" 36 | 37 | class Preetham : public Atmosphere { 38 | public: 39 | explicit Preetham(double turbidity); 40 | 41 | int GetOriginalNumberOfWavelengths() const override { return 3; } 42 | 43 | IrradianceSpectrum GetSunIrradiance(Length altitude, 44 | Angle sun_zenith) const override; 45 | 46 | RadianceSpectrum GetSkyRadiance(Length altitude, Angle sun_zenith, 47 | Angle view_zenith, Angle view_sun_azimuth) const override; 48 | 49 | private: 50 | double turbidity_; 51 | }; 52 | 53 | #endif // ATMOSPHERE_MODEL_PREETHAM_PREETHAM_H_ 54 | -------------------------------------------------------------------------------- /atmosphere/sun_direction.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | // Based on "Computing the Solar Vector" by Manuel Blanco-Muriel, 31 | // Diego C. Alarcon-Padilla, Teodoro Lopez-Moratalla, and Martin Lara-Coira, 32 | // in "Solar energy", vol 27, number 5, 2001 by Pergamon Press. 33 | // Original code available at http://www.psa.es/sdg/sunpos.htm. 34 | 35 | #include "atmosphere/sun_direction.h" 36 | 37 | #include 38 | #include 39 | 40 | // Declaration of some constants. 41 | #define PI 3.14159265358979323846 42 | #define TWO_PI (2 * PI) 43 | #define RAD (PI / 180) 44 | #define EARTH_MEAN_RADIUS 6371.01 // In km 45 | #define ASTRONOMICAL_UNIT 149597890 // In km 46 | 47 | void GetSunDirection(const Time& udt_time, const Location& udt_location, 48 | SunCoordinates *udt_sun_coordinates) { 49 | // Main variables. 50 | double elapsed_julian_days; 51 | double decimal_hours; 52 | double ecliptic_longitude; 53 | double ecliptic_obliquity; 54 | double right_ascension; 55 | double declination; 56 | 57 | // Auxiliary variables. 58 | double dy; 59 | double dx; 60 | 61 | // Calculate difference in days between the current Julian Day 62 | // and JD 2451545.0, which is noon 1 January 2000 Universal Time. 63 | { 64 | double julian_date; 65 | int64_t aux1; 66 | int64_t aux2; 67 | // Calculate time of the day in UT decimal hours. 68 | decimal_hours = 69 | udt_time.hours + (udt_time.minutes + udt_time.seconds / 60.0) / 60.0; 70 | // Calculate current Julian Day. 71 | aux1 = (udt_time.month - 14) / 12; 72 | aux2 = (1461 * (udt_time.year + 4800 + aux1)) / 4 + 73 | (367 * (udt_time.month - 2 - 12 * aux1)) / 12 - 74 | (3 * ((udt_time.year + 4900 + aux1) / 100)) / 4 + 75 | udt_time.day - 32075; 76 | julian_date = static_cast(aux2) - 0.5 + decimal_hours / 24.0; 77 | // Calculate difference between current Julian Day and JD 2451545.0 78 | elapsed_julian_days = julian_date - 2451545.0; 79 | } 80 | 81 | // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the 82 | // ecliptic in radians but without limiting the angle to be less than 2*Pi 83 | // (i.e., the result may be greater than 2*Pi). 84 | { 85 | double mean_longitude; // Radians 86 | double mean_anomaly; 87 | double omega; 88 | omega = 2.1429 - 0.0010394594 * elapsed_julian_days; 89 | mean_longitude = 4.8950630 + 0.017202791698 * elapsed_julian_days; 90 | mean_anomaly = 6.2400600 + 0.0172019699 * elapsed_julian_days; 91 | ecliptic_longitude = mean_longitude + 0.03341607 * sin(mean_anomaly) + 92 | 0.00034894 * sin(2 * mean_anomaly) - 0.0001134 - 93 | 0.0000203 * sin(omega); 94 | ecliptic_obliquity = 0.4090928 - 6.2140e-9 * elapsed_julian_days + 95 | 0.0000396 * cos(omega); 96 | } 97 | 98 | // Calculate celestial coordinates (right ascension and declination) in 99 | // radians but without limiting the angle to be less than 2*Pi (i.e., the 100 | // result may be greater than 2*Pi). 101 | { 102 | double sin_ecliptic_longitude; 103 | sin_ecliptic_longitude = sin(ecliptic_longitude); 104 | dy = cos(ecliptic_obliquity) * sin_ecliptic_longitude; 105 | dx = cos(ecliptic_longitude); 106 | right_ascension = atan2(dy, dx); 107 | if (right_ascension < 0.0) { 108 | right_ascension = right_ascension + TWO_PI; 109 | } 110 | declination = asin(sin(ecliptic_obliquity) * sin_ecliptic_longitude); 111 | } 112 | 113 | // Calculate local coordinates (azimuth and zenith angle) in degrees. 114 | { 115 | double greenwich_mean_sidereal_time; 116 | double local_mean_sidereal_time; 117 | double latitude_in_radians; 118 | double hour_angle; 119 | double cos_latitude; 120 | double sin_latitude; 121 | double cos_hour_angle; 122 | double parallax; 123 | greenwich_mean_sidereal_time = 124 | 6.6974243242 + 0.0657098283 * elapsed_julian_days + decimal_hours; 125 | local_mean_sidereal_time = 126 | (greenwich_mean_sidereal_time * 15 + udt_location.longitude) * RAD; 127 | hour_angle = local_mean_sidereal_time - right_ascension; 128 | latitude_in_radians = udt_location.latitude * RAD; 129 | cos_latitude = cos(latitude_in_radians); 130 | sin_latitude = sin(latitude_in_radians); 131 | cos_hour_angle = cos(hour_angle); 132 | udt_sun_coordinates->zenith = acos(cos_latitude * cos_hour_angle 133 | * cos(declination) + sin(declination) * sin_latitude); 134 | dy = -sin(hour_angle); 135 | dx = tan(declination) * cos_latitude - sin_latitude *cos_hour_angle; 136 | udt_sun_coordinates->azimuth = atan2(dy, dx); 137 | if (udt_sun_coordinates->azimuth < 0.0) { 138 | udt_sun_coordinates->azimuth = udt_sun_coordinates->azimuth + TWO_PI; 139 | } 140 | udt_sun_coordinates->azimuth = udt_sun_coordinates->azimuth / RAD; 141 | // Parallax Correction. 142 | parallax = (EARTH_MEAN_RADIUS / ASTRONOMICAL_UNIT) * 143 | sin(udt_sun_coordinates->zenith); 144 | udt_sun_coordinates->zenith = 145 | (udt_sun_coordinates->zenith + parallax) / RAD; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /atmosphere/sun_direction.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | // Based on "Computing the Solar Vector" by Manuel Blanco-Muriel, 31 | // Diego C. Alarcon-Padilla, Teodoro Lopez-Moratalla, and Martin Lara-Coira, 32 | // in "Solar energy", vol 27, number 5, 2001 by Pergamon Press. 33 | // Original code available at http://www.psa.es/sdg/sunpos.htm. 34 | 35 | #ifndef ATMOSPHERE_SUN_DIRECTION_H_ 36 | #define ATMOSPHERE_SUN_DIRECTION_H_ 37 | 38 | struct Time { 39 | int year; 40 | int month; 41 | int day; 42 | double hours; 43 | double minutes; 44 | double seconds; 45 | }; 46 | 47 | struct Location { 48 | double longitude; 49 | double latitude; 50 | }; 51 | 52 | struct SunCoordinates { 53 | double zenith; 54 | double azimuth; 55 | }; 56 | 57 | void GetSunDirection(const Time& udt_time, const Location& udt_location, 58 | SunCoordinates *udt_sun_coordinates); 59 | 60 | #endif // ATMOSPHERE_SUN_DIRECTION_H_ 61 | -------------------------------------------------------------------------------- /clear_sky_models.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 140 | 141 | -------------------------------------------------------------------------------- /physics/cie.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef PHYSICS_CIE_H_ 31 | #define PHYSICS_CIE_H_ 32 | 33 | #include "math/matrix.h" 34 | #include "math/vector.h" 35 | #include "physics/units.h" 36 | 37 | typedef dimensional::Vector3 Color; 38 | 39 | // The conversion factor between watts and lumens. 40 | constexpr auto MaxLuminousEfficacy = 683.0 * lm / watt; 41 | 42 | // The CIE color matching functions x_bar, y_bar and z_bar. See 43 | // https://en.wikipedia.org/wiki/CIE_1931_color_space#Color_matching_functions. 44 | const DimensionlessSpectrum& cie_x_bar_function(); 45 | const DimensionlessSpectrum& cie_y_bar_function(); 46 | const DimensionlessSpectrum& cie_z_bar_function(); 47 | 48 | // The conversion matrix from XYZ to linear sRGB color spaces. 49 | constexpr dimensional::Matrix3 XYZ_to_sRGB( 50 | +3.2404542, -1.5371385, -0.4985314, 51 | -0.9692660, +1.8760108, +0.0415560, 52 | +0.0556434, -0.2040259, +1.0572252); 53 | 54 | // The CIE S0, S1 and S2 components, allowing to compute the relative spectral 55 | // power distribution of a D65 illuminant with S = S0 + M1 S1 + M2 S2, where 56 | // M1 and M2 depend on the CIE xy chromaticities. 57 | // See https://en.wikipedia.org/wiki/Standard_illuminant for more details. 58 | const DimensionlessSpectrum& S0_function(); 59 | const DimensionlessSpectrum& S1_function(); 60 | const DimensionlessSpectrum& S2_function(); 61 | 62 | // Converts the given radiance spectrum to a luminance value, using the relation 63 | // L = MaxLuminousEfficacy * integral of cie_y_bar_function * spectrum 64 | Luminance GetLuminance(const RadianceSpectrum& spectrum); 65 | 66 | // Converts the given spectrum to a RGB color, by first converting the spectrum 67 | // to XYZ values with the x_bar, y_bar, z_bar functions, and then by converting 68 | // from XYZ to linear sRGB. 69 | Color GetSrgbColor(const RadianceSpectrum& spectrum); 70 | 71 | // Same as above, but using only number_of_wavelengths wavelengths, between the 72 | // given min and max. 73 | Color GetSrgbColor(const RadianceSpectrum& spectrum, Wavelength min_wavelength, 74 | Wavelength max_wavelength, int number_of_wavelengths); 75 | 76 | #endif // PHYSICS_CIE_H_ 77 | -------------------------------------------------------------------------------- /physics/cie_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "physics/cie.h" 31 | 32 | #include 33 | 34 | #include "test/test_case.h" 35 | 36 | class TestCie : public dimensional::TestCase { 37 | public: 38 | template 39 | TestCie(const std::string& name, T test) 40 | : TestCase("TestCie " + name, static_cast(test)) {} 41 | 42 | void TestColorFunctions() { 43 | const double kEps = 1e-12; 44 | ExpectNear(0.0001299, cie_x_bar_function()(360.0 * nm)(), kEps); 45 | ExpectNear(0.000003917, cie_y_bar_function()(360.0 * nm)(), kEps); 46 | ExpectNear(0.0006061, cie_z_bar_function()(360.0 * nm)(), kEps); 47 | ExpectNear(1.0567, cie_x_bar_function()(595.0 * nm)(), kEps); 48 | ExpectNear(0.6949, cie_y_bar_function()(595.0 * nm)(), kEps); 49 | ExpectNear(0.001, cie_z_bar_function()(595.0 * nm)(), kEps); 50 | } 51 | 52 | void TestSFunctions() { 53 | const double kEps = 1e-12; 54 | ExpectNear(61.5, S0_function()(360.0 * nm)(), kEps); 55 | ExpectNear(38.0, S1_function()(360.0 * nm)(), kEps); 56 | ExpectNear(5.3, S2_function()(360.0 * nm)(), kEps); 57 | ExpectNear(89.8, S0_function()(595.0 * nm)(), kEps); 58 | ExpectNear(-4.65, S1_function()(595.0 * nm)(), kEps); 59 | ExpectNear(2.65, S2_function()(595.0 * nm)(), kEps); 60 | } 61 | }; 62 | 63 | namespace { 64 | 65 | TestCie colorfunctions("colorfunctions", &TestCie::TestColorFunctions); 66 | TestCie sfunctions("sfunctions", &TestCie::TestSFunctions); 67 | 68 | } // anonymous namespace 69 | 70 | -------------------------------------------------------------------------------- /physics/units.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Eric Bruneton 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef PHYSICS_UNITS_H_ 31 | #define PHYSICS_UNITS_H_ 32 | 33 | #include "math/angle.h" 34 | #include "math/scalar.h" 35 | #include "math/scalar_function.h" 36 | 37 | // Defines a unit system for radiometric and photometric quantities, using the 38 | // following five base units: length, wavelength, solid angle, power and lumen 39 | // (wavelength is also a length, but we distinguish the two for increased 40 | // clarity). From this we derive the irradiance, radiance, spectral irradiance, 41 | // spectral radiance, candela, etc. 42 | 43 | typedef dimensional::Scalar<1, 0, 0, 0, 0> Length; 44 | typedef dimensional::Scalar<0, 1, 0, 0, 0> Wavelength; 45 | typedef dimensional::Scalar<0, 0, 1, 0, 0> SolidAngle; 46 | typedef dimensional::Scalar<0, 0, 0, 1, 0> Power; 47 | typedef dimensional::Scalar<0, 0, 0, 0, 1> LuminousPower; 48 | 49 | typedef dimensional::Number Number; 50 | typedef dimensional::Scalar<2, 0, 0, 0, 0> Area; 51 | typedef dimensional::Scalar<3, 0, 0, 0, 0> Volume; 52 | typedef dimensional::Scalar<-2, 0, 0, 1, 0> Irradiance; 53 | typedef dimensional::Scalar<-2, 0, -1, 1, 0> Radiance; 54 | typedef dimensional::Scalar<0, -1, 0, 1, 0> SpectralPower; 55 | typedef dimensional::Scalar<-2, -1, 0, 1, 0> SpectralIrradiance; 56 | typedef dimensional::Scalar<-2, -1, -1, 1, 0> SpectralRadiance; 57 | typedef dimensional::Scalar<-1, 0, 0, 0, 0> ScatteringCoefficient; 58 | typedef dimensional::Scalar<0, 0, -1, 0, 0> InverseSolidAngle; 59 | typedef dimensional::Scalar<-3, 0, 0, 0, 0> NumberDensity; 60 | typedef dimensional::Scalar<0, 0, -1, 0, 1> LuminousIntensity; 61 | typedef dimensional::Scalar<-2, 0, -1, 0, 1> Luminance; 62 | 63 | // A function from wavelength to values with some physical dimensions. 64 | template 65 | using WavelengthFunction = dimensional::ScalarFunction< 66 | 0, 1, 0, 0, 0, U1, U2, U3, U4, U5, 40, 360, 830>; 67 | 68 | // A function from wavelength to dimensionless values. 69 | typedef WavelengthFunction<0, 0, 0, 0, 0> DimensionlessSpectrum; 70 | 71 | // A function from wavelength to spectral power values. 72 | typedef WavelengthFunction<0, -1, 0, 1, 0> PowerSpectrum; 73 | 74 | // A function from wavelength to spectral irradiance values. 75 | typedef WavelengthFunction<-2, -1, 0, 1, 0> IrradianceSpectrum; 76 | 77 | // A function from wavelength to spectral radiance values. 78 | typedef WavelengthFunction<-2, -1, -1, 1, 0> RadianceSpectrum; 79 | 80 | // A function from wavelength to scattering coefficient values. 81 | typedef WavelengthFunction<-1, 0, 0, 0, 0> ScatteringSpectrum; 82 | 83 | // A function from wavelength to phase function values. 84 | typedef WavelengthFunction<0, 0, -1, 0, 0> PhaseFunctionSpectrum; 85 | 86 | // Provides aliases for the five base units, with shorter names than 87 | // Length::Unit(), Wavelength::Unit(), etc. 88 | 89 | constexpr Length m = Length::Unit(); 90 | constexpr Wavelength nm = Wavelength::Unit(); 91 | constexpr SolidAngle sr = SolidAngle::Unit(); 92 | constexpr Power watt = Power::Unit(); 93 | constexpr LuminousPower lm = LuminousPower::Unit(); 94 | 95 | // Provides aliases for some derived units. 96 | 97 | constexpr Length km = 1000.0 * m; 98 | constexpr Area m2 = Area::Unit(); 99 | constexpr Volume m3 = Volume::Unit(); 100 | constexpr Irradiance watt_per_square_meter = watt / m2; 101 | constexpr Radiance watt_per_square_meter_per_sr = watt / (m2 * sr); 102 | constexpr SpectralIrradiance watt_per_square_meter_per_nm = watt / (m2 * nm); 103 | constexpr SpectralRadiance watt_per_square_meter_per_sr_per_nm = 104 | watt / (m2 * sr * nm); 105 | constexpr LuminousIntensity cd = lm / sr; 106 | constexpr LuminousIntensity kcd = 1000.0 * cd; 107 | constexpr Luminance cd_per_square_meter = cd / m2; 108 | constexpr Luminance kcd_per_square_meter = kcd / m2; 109 | 110 | // Provides aliases for angle types and constants in the dimensional package, to 111 | // avoid having to use qualified type names and / or "using" directives in files 112 | // using this header. 113 | 114 | typedef dimensional::Angle Angle; 115 | constexpr Angle rad = dimensional::rad; 116 | constexpr Angle deg = dimensional::deg; 117 | constexpr double PI = dimensional::PI; 118 | constexpr Angle pi = dimensional::pi; 119 | 120 | #endif // PHYSICS_UNITS_H_ 121 | --------------------------------------------------------------------------------