Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
photon_map_light_transport.h
Go to the documentation of this file.
1#pragma once
2
10#include "Core/SurfaceHit.h"
17#include "Math/TVector3.h"
18#include "Math/Color/Spectrum.h"
19
20#include <Common/assertion.h>
21#include <Common/primitive_type.h>
22
23#include <cstddef>
24#include <limits>
25#include <algorithm>
26
27namespace ph { class Scene; }
28
29namespace ph
30{
31
36template<CPhoton Photon>
38 const Photon& photon,
39 const math::Vector3R& Ng,
40 const math::Vector3R& Ns,
41 const math::Vector3R& L,
42 const math::Vector3R& V,
43 const lta::SidednessAgreement& sidedness)
44{
45 if constexpr(Photon::template has<EPhotonData::GeometryNormal>())
46 {
47 const math::Vector3R photonNg = photon.template get<EPhotonData::GeometryNormal>();
48 if(photonNg.dot(Ng) < 0.1_r || // ~> 84.26 deg
49 photonNg.dot(Ns) < 0.2_r || // ~> 78.46 deg
50 !sidedness.isSidednessAgreed(photonNg, Ns, V) ||
51 !sidedness.isSidednessAgreed(photonNg, Ns, L))
52 {
53 return false;
54 }
55 }
56
57 return true;
58}
59
73template<CPhoton Photon>
75 const std::size_t viewPathLength,
76 const SurfaceHit& X,
77 const math::Spectrum& viewPathThroughput,
78 const TPhotonMapInfo<Photon>& photonMapInfo,
79 const Scene* scene,
80 const std::size_t minFullPathLength = 1,
81 const std::size_t maxFullPathLength = PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
82{
84
85 math::Spectrum lostEnergy(0);
86 if(!X.getSurfaceOptics())
87 {
88 return lostEnergy;
89 }
90
91 PH_ASSERT_GE(viewPathLength, 1);
92 PH_ASSERT_GE(minFullPathLength, 1);
93 PH_ASSERT_LE(minFullPathLength, maxFullPathLength);
94
95 // Cannot have path length = 1 lighting using only photon map--when we use a photon map, it is
96 // at least path length = 2 (can be even longer depending on the settings)
97
98 // Never contain 0-bounce photons
99 PH_ASSERT_GE(photonMapInfo.minPathLength, 1);
100
101 // Path length = 1 (0-bounce) lighting via path tracing (directly sample radiance)
102 if(viewPathLength == 1 && X.getSurfaceEmitter() && minFullPathLength == 1)
103 {
104 PH_ASSERT_IN_RANGE_INCLUSIVE(viewPathLength, minFullPathLength, maxFullPathLength);
105
106 math::Spectrum viewRadiance;
107 X.getSurfaceEmitter()->evalEmittedEnergy(X, &viewRadiance);
108 lostEnergy += viewPathThroughput * viewRadiance;
109 }
110
111 // +1 as when we merge view path with photon path, path length is at least increased by 1
112 const auto minPathLengthWithPhotonMap = photonMapInfo.minPathLength + 1;
113
114 // If we can **never** construct the path length from photon map, use path tracing
115 if(viewPathLength + 1 < minPathLengthWithPhotonMap &&
116 minFullPathLength <= viewPathLength + 1 && viewPathLength + 1 <= maxFullPathLength)
117 {
118 BsdfSampleQuery bsdfSample;
119 bsdfSample.inputs.set(X, -X.getIncidentRay().getDir());
120
121 math::Spectrum viewRadiance;
122 SampleFlow randomFlow;
123 if(DirectLight{scene}.bsdfSamplePathWithNee(
124 bsdfSample,
125 randomFlow,
126 &viewRadiance))
127 {
128 lostEnergy += viewPathThroughput * viewRadiance;
129 }
130 }
131
132 return lostEnergy;
133}
134
150template<CPhoton Photon>
152 const std::size_t viewPathLength,
153 const SurfaceHit& X,
154 const math::Spectrum& viewPathThroughput,
155 const TPhotonMapInfo<Photon>& photonMapInfo,
156 const Scene* scene,
157 const std::size_t minFullPathLength = 1,
158 const std::size_t maxFullPathLength = PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
159{
161
162 math::Spectrum lostEnergy(0);
163 if(!X.getSurfaceOptics())
164 {
165 return lostEnergy;
166 }
167
168 PH_ASSERT_GE(viewPathLength, 1);
169 PH_ASSERT_GE(minFullPathLength, 1);
170 PH_ASSERT_LE(minFullPathLength, maxFullPathLength);
171
172 // Cannot have path length = 1 lighting using only photon map--when we use a photon map, it is
173 // at least path length = 2 (can be even longer depending on the settings)
174
175 // Never contain 0-bounce photons
176 PH_ASSERT_GE(photonMapInfo.minPathLength, 1);
177
178 // If we extend the view path length from N (current) to N + 1, this means we are not using photon
179 // map to approximate lighting for path length = N' = `N + photonMapInfo.minPathLength`.
180 // We will lose energy for path length = N' if we do nothing. Here we use path tracing to
181 // find the energy that would otherwise be lost.
182 if(minFullPathLength <= viewPathLength + photonMapInfo.minPathLength &&
183 viewPathLength + photonMapInfo.minPathLength <= maxFullPathLength)
184 {
185 math::Spectrum viewRadiance;
186 SampleFlow randomFlow;
187 if(IndirectLight{scene}.bsdfSamplePathWithNee(
188 X,
189 randomFlow,
190 photonMapInfo.minPathLength,// we are already on view path of length N
192 &viewRadiance,
193 1,// `X` is likely a delta or glossy surface, delay RR slightly
194 viewPathThroughput))
195 {
196 lostEnergy += viewRadiance;
197 }
198 }
199
200 return lostEnergy;
201}
202
217template<CPhoton Photon>
219 const std::size_t viewPathLength,
220 const SurfaceHit& X,
221 const math::Spectrum& viewPathThroughput,
222 const TPhotonMapInfo<Photon>& photonMapInfo,
223 const Scene* scene,
224 const std::size_t minFullPathLength = 1,
225 const std::size_t maxFullPathLength = PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
226{
228
229 math::Spectrum lostEnergy(0);
230 if(!X.getSurfaceOptics())
231 {
232 return lostEnergy;
233 }
234
235 PH_ASSERT_GE(viewPathLength, 1);
236 PH_ASSERT_GE(minFullPathLength, 1);
237 PH_ASSERT_LE(minFullPathLength, maxFullPathLength);
238
239 // Never contain 0-bounce photons
240 PH_ASSERT_GE(photonMapInfo.minPathLength, 1);
241
242 // For path length = N (current), we can construct light transport path lengths with photon map,
243 // all at once, for the range [N_min, N_max] =
244 // [`N + photonMapInfo.minPathLength`, `N + photonMapInfo.maxPathLength`].
245 // For path lengths < N_min, they should be accounted for by `estimate_lost_energy_for_extend()`
246 // already. For all path lengths > N_max, use path tracing, which is done below:
247
248 const auto minLostFullPathLength = viewPathLength + photonMapInfo.maxPathLength + 1;
249
250 // Will also skip this if it is practically infinite number of bounces already
251 const bool isAlreadyEnoughBounces =
252 minLostFullPathLength > PMCommonParams::DEFAULT_MAX_PATH_LENGTH;
253
254 if(!isAlreadyEnoughBounces && minLostFullPathLength <= maxFullPathLength)
255 {
256 const auto minLostFullPathLengthClipped = std::max(
257 minFullPathLength, minLostFullPathLength);
258 PH_ASSERT_GE(minLostFullPathLengthClipped, viewPathLength);
259
260 math::Spectrum viewRadiance;
261 SampleFlow randomFlow;
262 if(IndirectLight{scene}.bsdfSamplePathWithNee(
263 X,
264 randomFlow,
265 minLostFullPathLengthClipped - viewPathLength,// we are already on view path of length N
266 std::numeric_limits<std::size_t>::max(),
268 &viewRadiance,
269 0,// the path length is likely long already, do RR immediately
270 viewPathThroughput))
271 {
272 lostEnergy += viewRadiance;
273 }
274 }
275
276 return lostEnergy;
277}
278
279}// end namespace ph
void set(const BsdfEvalInput &evalInput)
Definition BsdfSampleQuery.cpp:7
Information for generating a BSDF sample.
Definition BsdfSampleQuery.h:141
Input inputs
Definition BsdfSampleQuery.h:147
virtual void evalEmittedEnergy(const SurfaceHit &Xe, math::Spectrum *out_energy) const =0
Evaluate emitted energy from a point on the surface.
static constexpr uint32 DEFAULT_MAX_PATH_LENGTH
Definition PMCommonParams.h:15
const math::Vector3R & getDir() const
Definition Ray.h:214
A sample with arbitrary dimensions with fine-grained sampling control.
Definition SampleFlow.h:19
A unified interface for accessing cooked content in a visual world.
Definition Scene.h:27
General information about a ray-surface intersection event.
Definition SurfaceHit.h:59
const Ray & getIncidentRay() const
Convenient method for getRay() where getReason() contains ESurfaceHitReason::IncidentRay.
Definition SurfaceHit.h:175
const Emitter * getSurfaceEmitter() const
Definition SurfaceHit.cpp:61
const SurfaceOptics * getSurfaceOptics() const
Definition SurfaceHit.cpp:67
Carries common informatiom for a photon map.
Definition TPhotonMap.h:24
uint32 minPathLength
Definition TPhotonMap.h:27
uint32 maxPathLength
Definition TPhotonMap.h:28
Russian roulette random termination scheme.
Definition RussianRoulette.h:16
Definition SidednessAgreement.h:32
bool isSidednessAgreed(const math::Vector3R &Ng, const math::Vector3R &Ns, const math::Vector3R &vec) const
Definition SidednessAgreement.h:104
Estimate direct lighting for a surface point. This is a lightweight helper type for estimating direct...
Definition TDirectLightEstimator.h:31
Estimate indirect lighting for a surface point.
Definition TIndirectLightEstimator.h:23
Definition TTristimulusSpectrum.h:11
T dot(const Derived &rhs) const
Definition TVectorNBase.ipp:14
The root for all renderer implementations.
Definition EEngineProject.h:6
math::Spectrum estimate_lost_energy_for_extending(const std::size_t viewPathLength, const SurfaceHit &X, const math::Spectrum &viewPathThroughput, const TPhotonMapInfo< Photon > &photonMapInfo, const Scene *scene, const std::size_t minFullPathLength=1, const std::size_t maxFullPathLength=PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
Estimate the energy that is otherwise lost forever if the path is extended. The estimation is for the...
Definition photon_map_light_transport.h:151
math::Spectrum estimate_lost_energy_for_merging(const std::size_t viewPathLength, const SurfaceHit &X, const math::Spectrum &viewPathThroughput, const TPhotonMapInfo< Photon > &photonMapInfo, const Scene *scene, const std::size_t minFullPathLength=1, const std::size_t maxFullPathLength=PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
Estimate the energy that is otherwise lost forever if the path is merged. The estimation is for the c...
Definition photon_map_light_transport.h:218
math::Spectrum estimate_certainly_lost_energy(const std::size_t viewPathLength, const SurfaceHit &X, const math::Spectrum &viewPathThroughput, const TPhotonMapInfo< Photon > &photonMapInfo, const Scene *scene, const std::size_t minFullPathLength=1, const std::size_t maxFullPathLength=PMCommonParams::DEFAULT_MAX_PATH_LENGTH)
Estimate the energy that can never be obtained by utilizing a photon map. The estimation is for the c...
Definition photon_map_light_transport.h:74
bool accept_photon_by_surface_topology(const Photon &photon, const math::Vector3R &Ng, const math::Vector3R &Ns, const math::Vector3R &L, const math::Vector3R &V, const lta::SidednessAgreement &sidedness)
Definition photon_map_light_transport.h:37