Arty
lights.h
1 #ifndef LIGHTS_H
2 #define LIGHTS_H
3 
4 #include "color.h"
5 #include "float3.h"
6 #include "samplers.h"
7 
9 struct EmissionSample {
13  float pdf_area;
14  float pdf_dir;
15  float cos;
16 
17  EmissionSample() {}
18  EmissionSample(const float3& p, const float3& d, const rgb& i, float pa, float pd, float c)
19  : pos(p), dir(d), intensity(i), pdf_area(pa), pdf_dir(pd), cos(c)
20  {}
21 };
22 
27  float pdf_area;
28  float pdf_dir;
29  float cos;
30 
32  DirectLightingSample(const float3& p, const rgb& i, float pa, float pd, float c)
33  : pos(p), intensity(i), pdf_area(pa), pdf_dir(pd), cos(c)
34  {}
35 };
36 
38 struct EmissionValue {
40  float pdf_area;
41  float pdf_dir;
42 
43  EmissionValue() {}
44  EmissionValue(const rgb& i, float pa, float pd)
45  : intensity(i), pdf_area(pa), pdf_dir(pd)
46  {}
47 };
48 
50 class Light {
51 public:
52  virtual ~Light() {}
53 
55  virtual DirectLightingSample sample_direct(const float3& from, Sampler& sampler) const = 0;
56 
58  virtual EmissionSample sample_emission(Sampler& sampler) const = 0;
59 
61  virtual EmissionValue emission(const float3& dir, float u, float v) const = 0;
62 
64  virtual bool has_area() const = 0;
65 
66 protected:
67  EmissionSample make_emission_sample(const float3& pos, const float3& dir, const rgb& intensity, float pdf_area, float pdf_dir, float cos) const {
68  return pdf_area > 0 && pdf_dir > 0 && cos > 0
69  ? EmissionSample(pos, dir, intensity, pdf_area, pdf_dir, cos)
70  : EmissionSample(pos, dir, rgb(0.0f), 1.0f, 1.0f, 1.0f);
71  }
72 
73  DirectLightingSample make_direct_sample(const float3& pos, const rgb& intensity, float pdf_area, float pdf_dir, float cos) const {
74  return pdf_area > 0 && pdf_dir > 0 && cos > 0
75  ? DirectLightingSample(pos, intensity, pdf_area, pdf_dir, cos)
76  : DirectLightingSample(pos, rgb(0.0f), 1.0f, 1.0f, 1.0f);
77  }
78 };
79 
81 class PointLight : public Light {
82 public:
83  PointLight(const float3& p, const rgb& c) : pos(p), color(c * (1.0f / (4.0f * pi))) {}
84 
85  DirectLightingSample sample_direct(const float3&, Sampler&) const override final {
86  return make_direct_sample(pos, color, 1.0f, uniform_sphere_pdf(), 1.0f);
87  }
88 
89  EmissionSample sample_emission(Sampler& sampler) const override final {
90  auto sample = sample_uniform_sphere(sampler(), sampler());
91  return make_emission_sample(pos, sample.dir, color, 1.0f, sample.pdf, 1.0f);
92  }
93 
94  EmissionValue emission(const float3& /*dir*/, float /*u*/, float /*v*/) const override final {
95  return EmissionValue(rgb(0.0f), 1.0f, 1.0f);
96  }
97 
98  bool has_area() const override final {
99  return false;
100  }
101 
102 private:
103  float3 pos;
104  rgb color;
105 };
106 
108 class TriangleLight : public Light {
109 public:
110  TriangleLight(const float3& v0, const float3& v1, const float3& v2, const rgb& c)
111  : v0(v0), v1(v1), v2(v2), color(c)
112  {
113  n = cross(v1 - v0, v2 - v0);
114  auto len = length(n);
115  auto area = len * 0.5f;
116  inv_area = 1.0f / area;
117  n *= inv_area * 0.5f;
118  }
119 
120  DirectLightingSample sample_direct(const float3& from, Sampler& sampler) const override final {
121  auto pos = sample(sampler);
122  auto dir = from - pos;
123  float cos = dot(dir, n) / length(dir);
124  return make_direct_sample(pos, color, inv_area, cosine_hemisphere_pdf(cos), cos);
125  }
126 
127  EmissionSample sample_emission(Sampler& sampler) const override final {
128  auto pos = sample(sampler);
129  auto sample = sample_cosine_hemisphere(gen_local_coords(n), sampler(), sampler());
130  return make_emission_sample(pos, sample.dir, color, inv_area, sample.pdf, dot(sample.dir, n));
131  }
132 
133  EmissionValue emission(const float3& dir, float /*u*/, float /*v*/) const override final {
134  auto cos = cosine_hemisphere_pdf(dot(dir, n));
135  return cos > 0
136  ? EmissionValue(color, inv_area, cosine_hemisphere_pdf(dot(dir, n)))
137  : EmissionValue(rgb(0.0f), 1.0f, 1.0f);
138  }
139 
140  bool has_area() const override final {
141  return true;
142  }
143 
144 private:
145  float3 sample(Sampler& sampler) const {
146  float u = sampler();
147  float v = sampler();
148  if (u + v > 1.0f) {
149  u = 1.0f - u;
150  v = 1.0f - v;
151  }
152  return lerp(v0, v1, v2, u, v);
153  }
154 
155  float3 v0, v1, v2;
156  float3 n;
157  float inv_area;
158  rgb color;
159 };
160 
161 #endif // LIGHTS_H
Base class for all lights.
Definition: lights.h:50
Sampler object, used at the level of the integrator to control how the random number generation is do...
Definition: samplers.h:12
rgb intensity
Intensity along the direction.
Definition: lights.h:39
Definition: float3.h:10
float3 pos
Position on the light source.
Definition: lights.h:10
bool has_area() const override final
Returns true if the light has an area (i.e. can be hit by a ray).
Definition: lights.h:98
DirectLightingSample sample_direct(const float3 &from, Sampler &sampler) const override final
Samples direct illumination from this light source at the given point on a surface.
Definition: lights.h:120
float3 dir
Direction of the light going outwards.
Definition: lights.h:11
rgb intensity
Intensity along the direction.
Definition: lights.h:12
float cos
Cosine between the direction and the light source geometry.
Definition: lights.h:29
float pdf_area
Probability to sample the point on the light.
Definition: lights.h:27
EmissionValue emission(const float3 &, float, float) const override final
Returns the emission of a light source (only for light sources with an area).
Definition: lights.h:94
EmissionSample sample_emission(Sampler &sampler) const override final
Samples the emitting surface of the light.
Definition: lights.h:127
float pdf_area
Probability to sample the point on the light.
Definition: lights.h:13
DirectLightingSample sample_direct(const float3 &, Sampler &) const override final
Samples direct illumination from this light source at the given point on a surface.
Definition: lights.h:85
Emission value at a given point on the light surface.
Definition: lights.h:38
float pdf_dir
Probability to sample the direction on the light, conditioned on the point on the light source...
Definition: lights.h:14
float pdf_dir
Probability to sample the direction using emission sampling.
Definition: lights.h:41
EmissionSample sample_emission(Sampler &sampler) const override final
Samples the emitting surface of the light.
Definition: lights.h:89
float pdf_dir
Probability to sample the direction using emission sampling.
Definition: lights.h:28
Result from sampling a light source.
Definition: lights.h:9
float cos
Cosine between the direction and the light source geometry.
Definition: lights.h:15
Result from sampling direct lighting from a light source.
Definition: lights.h:24
Triangle light source, useful to represent area lights made of meshes.
Definition: lights.h:108
bool has_area() const override final
Returns true if the light has an area (i.e. can be hit by a ray).
Definition: lights.h:140
rgb intensity
Intensity along the direction.
Definition: lights.h:26
Simple point light, with intensity decreasing quadratically.
Definition: lights.h:81
EmissionValue emission(const float3 &dir, float, float) const override final
Returns the emission of a light source (only for light sources with an area).
Definition: lights.h:133
Definition: color.h:9
float3 pos
Position on the light source.
Definition: lights.h:25
float pdf_area
Probability to sample the point on the light.
Definition: lights.h:40