This is README file for RADIANCE photon flow. This software was developed as part of the project "Three-Dimensional Light Flow" hosted by Tokyo University of Science, supported by the JSPS Grants-in-Aid for Scientific Research (KAKENHI) under the grant number JP19KK0115. $Revision: 1.3 $ $Date: 2020/11/16 22:41:09 $ INTRODUCTION These source files implement a modified volume photon density estimate in RADIANCE to evaluate the illuminance of a physical lightfield using photon flow. This code is an experimental variant of the RADIANCE photon map extension intended for testing prior to committing it to the RADIANCE CVS as part of the official distribution. Whether this (admittedly specialised) functionality should be made available to the RADIANCE community as a build option is debatable and may be decided in due course. This code is essentially a C implementation of the prototype Python script volPhotonIllum.py. As such, it is orders of magnitude faster, which comes to bear with large photon maps and many sensor positions. One crucial difference between the RADIANCE and Python implementation is that the former performs photon lookups in terms of a fixed number of photons around the sensor position (nearest neighbour search), while the latter does so in terms of a fixed radius (range search). The RADIANCE implementation however offers an additional maximum radius parameter for optimisation, which is infact required to obtain the specified number of photons in conjunction with photon flow (see USAGE below). The illuminance evaluated from photon flow approximates Cuttle's cubic illuminance, which in turn quantifies a sensor position in a physical light field. Photon flow constitues volume photons deposited by mkpmap in a participating medium (mist); due to the interaction of a photon with the medium, it will be deposited at multiple locations along its path. Each photon path has a unique ID consisting of a prefix (mkpmap child process number if multiprocessing) and a suffix (a 32-bit serial ray number); these can be output by pmapdump with the -a and -P options. Evaluating photon flow at a given position in the lightfield requires pruning photons with identical path IDs within the search radius, keeping only the closest photon from each intercepted path. To this end, the search routines use filtering routines which maintain a lookup table containing the intercepted path IDs in order to identify duplicates. Some code was refactored to filter photons and their path IDs in a new module pmapfilt.c shared by the two underlying data structures which store the photon map: the (legacy) kd-tree and the out-of-core octree. The nearest-neighbour search routines of both variants were modified to use these filter functions via callbacks to facilitate maintenance. In this way, volume photons can be filtered for duplicate path IDs "on the fly" as the search progresses, as opposed to pruning these a posteriori, resulting in a lower photon count. In addition, a new volume photon density estimate routine volumePhotonSphIrrad() was added to pmapdens.c to evaluate the photon flow; this routine differs from the already existing volume photon density estimate routine volumePhotonDensity() in that it does not apply the Henyey-Greenstein phase function to compute outscattering, and completely ignores the participating medium. Because photon flow not only includes photons that have been reflected off one or more surfaces (indirect contributions), but also photons that have just been emitted from light sources (direct contributions), the new volume photon density estimate is called by multiDirectPmap() in pmapsrc.c, which normally calls the direct photon map density estimate (typically only used for debugging). To prevent overcounting, the ambient calculation is therefore disabled in photon flow mode (see ampPmap() in pmapamb.c). COMPILING The files in this package are intended to replace those from the current RADIANCE CVS release; these are confined to the ray/src/rt subdirectory, where the photon mapping code resides alongside RADIANCE's raytracing code. The photon flow code is built by defining PMAP_PHOTONFLOW during compilation of the RADIANCE suite. This may be accelerated by only (re)compiling in ray/src/rt if a RADIANCE build already exists: rmake OPT+=-DPMAP_PHOTONFLOW install The photon flow code contains debugging code that can be output for each photon path lookup table operation. In addition, a built-in sanity check of the lookup table will be run after each such operation. These options can be enabled by defining PMAP_DEBUGPATHS in addition to PMAP_PHOTONFLOW: rmake OPT+="-DPMAP_PHOTONFLOW -DPMAP_DEBUGPATHS" install Note that these options are independent of the underlying data structure used to store the photon map. The default options build the legacy kd-tree. If a larger, out-of-core photon map is desired (to accommodate >1 billion photons, for example), this build option must be enabled by defining PMAP_OOC: rmake OPT+="-DPMAP_OOC -DPMAP_PHOTONFLOW" install For details, see the RADIANCE Out-Of-Core Photon Map Technical Report at http://dx.doi.org/10.13140/RG.2.1.2158.9363 USAGE A volume photon map representing the physical lightfield is generated with mkpmap by defining a global participating medium on the command line that does not absorb (albedo = 1.0) nor scatter (scattering eccentricity = 1), and thus does not alter a photon's trajectory along its path as it traverses the medium: mkpmap -apv photonFlow.vpm 1M [-apo port1 ... -apo portN] -apD 0.001 \ -me .1 .1 .1 -ma 1 1 1 -mg 1 scene.oct The extinction -me is a free parameter here and determines the photon density per path; this should be higher than typical for mist to capture sufficient detail of the physical lightfield; a value of .1 is already a very dense medium, but can be increased if more detail is desired. There is a caveat with using high values of -me, namely that the two-pass photon distribution algorithm used by mkpmap to achieve the target number of photons fails. The fraction of photons emitted in the 1st pass (prepass) is specified with -apD (predistribution factor). Its default value of 0.25 is tuned for "well behaved" geometry and materials using global or caustic photons. This value is too high for volume photons in a dense participating medium, and the photon distribution overflows in the prepass with a "photon map overflow" error, meaning that the target photon count was already exceeded (technically this does not yield an incorrect solution, but it's not what the user wanted). When using photon flow, this value should be significantly reduced from its default to prevent an overflow in the prepass; in the example above, an -apD of 0.001 accommodates the size of the photon map that results with a relatively high -me of 0.1. Once the volume photon map has been generated, the physical lightfield it represents can be evaluated using rtrace. Photon flow is enabled using a new (experimental) option -apF, which disables the normal ambient calculation and performs the new volume photon density estimate at the given sensor position(s). Because the ambient calculation is entirely circumvented, the -ab parameter is now irrelevant; the volume photon density is evaluated immediately at each sensor position: rtrace -h -I -ap photonFlow.vpm 250 -apF -am 100 scene.oct < sensors.dat \ rcalc -e '$1 = 179 * $1' In this example, the irradiance from photon flow is evaluated with a bandwidth of 250 photons (from unique paths as described above) around each sensor position, and converted to illuminance using rcalc with a standard luminous efficacy for daylight of 179 lm/W. Here too, there is a caveat regarding the maximum search radius used by the nearest neighbour search routines to locate photons. This radius is automatically initialised from the average photon density to balance performance against conservative pruning, and is optimised for "well behaved" global and caustic photon maps. However, this fails with photon flow due to the additional pruning action of the photon path filter, resulting in far fewer photons for the density estimate than requested, which in turn increases noise in the illuminance. In this case, rtrace issues a "short lookup in photon flow" warning, and recommends using the -am parameter. The -am parameter manually sets the maximum search radius to fine-tune the lookups; if set, the bandwidth becomes the _maximum_ number of photons that will be sought within the given radius. This can be used, for example, to limit bias by setting the radius to the sensor grid spacing (or a multiple thereof, to allow for some overlap). Even if set, rtrace may still issue occasional warnings recommending a higher radius; this is left to the user's discretion, as increasing the radius also increases bias, and may indicate that the size of the photon map overall may be too small for the given sensor grid spacing. Finally, the photon flow distribution may be visualised by either dumping it as a RADIANCE scene description, and rendering the photons as spheres, e.g. pmapdump -n 1m photonFlow.vpm | objview or by dumping it as a point list for use in a point cloud viewer: pmapdump -a -f -N -P -n 1m photonFlow.vpm > photonFlow.xyz In the latter example, pmapdump also outputs each photon's radiant flux (in W), its direction (or normal for surface-bound global and caustic photons), and its path ID for subsequent filtering. See the pmapdump man page or the RADIANCE photon map manual at http://dx.doi.org/10.13140/RG.2.1.4330.8405/1 for details. CONCLUSION This code is experimental and needs thorough testing; I welcome your feedback in terms of the results but also its usage. The integration of photon flow into the RADIANCE suite is currently very hacky and could be improved. In particular, there may be a more elegant way to make this functionality accessible than using an obscure parameter -apF. Once these issues have been sorted out, we should consider whether the code be made public and uploaded to the RADIANCE CVS repository. Many thanks in advance for your cooperation and feedback. Happy photon flowing! --Roland Schregle (roland.schregle@{hslu.ch, gmail.com})