Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TIndirectLightEstimator.ipp
Go to the documentation of this file.
1#pragma once
2
9#include "Core/SurfaceHit.h"
10#include "Core/Ray.h"
11#include "Math/TVector3.h"
12
13#include <Common/assertion.h>
14
15namespace ph::lta
16{
17
18template<ESidednessPolicy POLICY>
20 : m_scene(scene)
21{
22 PH_ASSERT(scene);
23}
24
25template<ESidednessPolicy POLICY>
27 const SurfaceHit& X,
28 SampleFlow& sampleFlow,
29 const std::size_t pathLength,
30 const RussianRoulette& rr,
31 math::Spectrum* const out_Lo,
32 const std::size_t rrBeginPathLength,
33 const math::Spectrum& initialPathWeight) const
34{
35 PH_ASSERT_GE(pathLength, 1);
36
37 const SurfaceTracer surfaceTracer{m_scene};
38 const TDirectLightEstimator<POLICY> directLight{m_scene};
39 const BsdfQueryContext bsdfCtx{POLICY};
40
41 SurfaceHit currentHit = X;
42 math::Spectrum pathThroughput = initialPathWeight;
43 real rrScale = 1.0_r;
44
45 std::size_t currentPathLength = 0;
46 while(currentPathLength < pathLength)// can extend by 1?
47 {
48 if(currentPathLength >= rrBeginPathLength)
49 {
50 real rrSurvivalProb;
51 if(rr.surviveOnLuminance(pathThroughput * rrScale, sampleFlow, &rrSurvivalProb))
52 {
53 pathThroughput *= 1.0_r / rrSurvivalProb;
54 }
55 else
56 {
57 return false;
58 }
59 }
60
61 const math::Vector3R V = currentHit.getIncidentRay().getDir().mul(-1);
62
63 BsdfSampleQuery bsdfSample{bsdfCtx};
64 bsdfSample.inputs.set(currentHit, V);
65
66 // Sample direct lighting
67 if(currentPathLength + 1 == pathLength)
68 {
70 if(directLight.bsdfSamplePathWithNee(bsdfSample, sampleFlow, &Lo))
71 {
72 if(out_Lo) { *out_Lo = pathThroughput * Lo; }
73 return true;
74 }
75 }
76 // Extend the path
77 else
78 {
79 SurfaceHit nextHit;
80 if(!surfaceTracer.bsdfSampleNextSurface(bsdfSample, sampleFlow, &nextHit) ||
81 !bsdfSample.outputs.isMeasurable())
82 {
83 return false;
84 }
85
86 currentHit = nextHit;
87 pathThroughput *= bsdfSample.outputs.getPdfAppliedBsdfCos();
88
89 // Prevent premature termination of the path due to solid angle compression/expansion
90 rrScale /= bsdfSample.outputs.getRelativeIor2();
91 }
92
93 ++currentPathLength;
94 }
95
96 return false;
97}
98
99template<ESidednessPolicy POLICY>
101 const SurfaceHit& X,
102 SampleFlow& sampleFlow,
103 const std::size_t minPathLength,
104 const std::size_t maxPathLength,
105 const RussianRoulette& rr,
106 math::Spectrum* const out_Lo,
107 const std::size_t rrBeginPathLength,
108 const math::Spectrum& initialPathWeight) const
109{
110 PH_ASSERT_GE(minPathLength, 1);
111 PH_ASSERT_LE(minPathLength, maxPathLength);
112
113 const SurfaceTracer surfaceTracer{m_scene};
114 const TDirectLightEstimator<POLICY> directLight{m_scene};
115 const BsdfQueryContext bsdfCtx{POLICY};
116
117 SurfaceHit currentHit = X;
118 math::Spectrum pathThroughput = initialPathWeight;
119 math::Spectrum accuLo(0);
120 real rrScale = 1.0_r;
121
122 std::size_t currentPathLength = 0;
123 while(currentPathLength < maxPathLength)// can extend by 1?
124 {
125 if(currentPathLength >= rrBeginPathLength)
126 {
127 real rrSurvivalProb;
128 if(rr.surviveOnLuminance(pathThroughput * rrScale, sampleFlow, &rrSurvivalProb))
129 {
130 pathThroughput *= 1.0_r / rrSurvivalProb;
131 }
132 else
133 {
134 break;
135 }
136 }
137
138 const math::Vector3R V = currentHit.getIncidentRay().getDir().mul(-1);
139
140 BsdfSampleQuery bsdfSample{bsdfCtx};
141 bsdfSample.inputs.set(currentHit, V);
142
143 // Account for energy from the specified path length range
144 PH_ASSERT_LE(currentPathLength + 1, maxPathLength);
145 if(currentPathLength + 1 >= minPathLength)
146 {
148 std::optional<SurfaceHit> nextHit;
149 if(!directLight.bsdfSamplePathWithNee(bsdfSample, sampleFlow, &Lo, &nextHit) ||
150 !bsdfSample.outputs.isMeasurable() ||
151 !nextHit)
152 {
153 break;
154 }
155
156 accuLo += pathThroughput * Lo;
157 currentHit = *nextHit;
158 }
159 // Extend the path
160 else
161 {
162 SurfaceHit nextHit;
163 if(!surfaceTracer.bsdfSampleNextSurface(bsdfSample, sampleFlow, &nextHit) ||
164 !bsdfSample.outputs.isMeasurable())
165 {
166 break;
167 }
168
169 currentHit = nextHit;
170 }
171
172 pathThroughput *= bsdfSample.outputs.getPdfAppliedBsdfCos();
173
174 // Prevent premature termination of the path due to solid angle compression/expansion
175 rrScale /= bsdfSample.outputs.getRelativeIor2();
176
177 ++currentPathLength;
178 }
179
180 if(out_Lo) { *out_Lo = accuLo; }
181
182 return true;
183}
184
185}// end namespace ph::lta
The environment a BSDF query is performed under.
Definition BsdfQueryContext.h:13
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
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
Russian roulette random termination scheme.
Definition RussianRoulette.h:16
bool surviveOnLuminance(const math::Spectrum &s, SampleFlow &sampleFlow, real *out_survivalProbability) const
Definition RussianRoulette.h:30
Common operations for surface tracing. This class also handles many subtle cases for surface tracing....
Definition SurfaceTracer.h:35
Estimate direct lighting for a surface point. This is a lightweight helper type for estimating direct...
Definition TDirectLightEstimator.h:31
TIndirectLightEstimator(const Scene *scene)
Definition TIndirectLightEstimator.ipp:19
bool bsdfSamplePathWithNee(const SurfaceHit &X, SampleFlow &sampleFlow, std::size_t pathLength, const RussianRoulette &rr, math::Spectrum *out_Lo=nullptr, std::size_t rrBeginPathLength=0, const math::Spectrum &initialPathWeight=math::Spectrum(1)) const
Constructing path with BSDF sampling and estimate lighting with both BSDF sampling and next-event est...
Definition TIndirectLightEstimator.ipp:26
Definition TTristimulusSpectrum.h:11
Derived mul(const Derived &rhs) const
Definition TArithmeticArrayBase.ipp:98
Light transport algorithms.
Definition enums.h:6