-
Notifications
You must be signed in to change notification settings - Fork 1
/
area_light.h
154 lines (120 loc) · 4.56 KB
/
area_light.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef _AREA_LIGHT_H_
#define _AREA_LIGHT_H_
#include "common.h"
#include "rgb.h"
#include "light.h"
#include "surface.h"
namespace Renzoku {
class AreaLight : public Light {
public:
AreaLight(Surface *_surface, const Rgb &emission);
virtual Light::Type get_light_type() const {
return Light::AREA_LIGHT;
}
inline virtual bool hit(const Ray &r, Float tmin, Float tmax, Float time, HitRecord &record) const;
inline virtual bool hit(const Ray &r, Float tmin, Float tmax, Float time) const;
inline virtual Float area() const;
inline virtual Rgb power() const;
/**
* Return a point on the light
*/
inline virtual void sample(Random &rd, Vec3 &p, Vec3 &n, Float &pdf) const;
/**
* Return a point and an outgoing direction from the light.
*/
inline virtual void sample(Random &rd, Vec3 &p, Vec3 &n, Vec3 &wo, Rgb &radiance, Float &pdf) const;
inline virtual void sample(Random &rd, Vec3 &p, Vec3 &n, Vec3 &wo, Rgb &radiance, Float &pdf_p, Float &pdf_wo) const;
/**
* Return the probability of sampling a point on the light.
*/
inline virtual Float pdf(const Vec3 &p) const;
/**
* Return the probability of sampling a point and a direction from the light.
*/
inline virtual Float pdf(const Vec3 &p, const Vec3 &n, const Vec3 &wo) const;
inline virtual void pdf(const Vec3 &p, const Vec3 &n, const Vec3 &wo, Float &pdf_p, Float &pdf_wo) const;
/**
* Given a point on the light, return probability of a direction
*/
inline virtual Float pdf_wo(const Vec3 &p, const Vec3 &wo) const;
/**
* Consider receiver location and sample.
*/
inline virtual void sample(Random &rd, Vec3 &p, Vec3 &n, Float &pdf, const Receiver &patch) const;
inline virtual Float pdf(const Vec3 &p, const Receiver &patch) const;
/**
* Query the out-going radiance at a point on the light. Useful for cases when some ray hits the light.
*/
virtual void query(const Vec3 &p, const Vec3 &n, const Vec3 &wo, Rgb &radiance) const;
inline Surface *get_surface() const;
inline void set_surface(Surface *surface);
virtual Rgb first_bounce(Scene *scene, const Receiver &r, DirectionSampler *dir_sampler) const;
virtual Rgb irradiance(Scene *scene, const LocalGeometry &dg, LightSamplingRecord &sr) const;
protected:
Surface *surface;
Rgb radiance;
};
inline Surface *AreaLight::get_surface() const {
return surface;
}
inline void AreaLight::set_surface(Surface *surface) {
this->surface = surface;
}
inline bool AreaLight::hit(const Ray &r, Float tmin, Float tmax, Float time, HitRecord &record) const {
return surface->hit(r, tmin, tmax, time, record);
}
inline bool AreaLight::hit(const Ray &r, Float tmin, Float tmax, Float time) const {
return surface->hit(r, tmin, tmax, time);
}
inline Float AreaLight::area() const {
return surface->area();
}
inline Rgb AreaLight::power() const {
return radiance * area() * A_PI; // integrate L cos(theta) sin(theta) d(theta) d(phi) = pi
}
inline void AreaLight::sample(Random &rd, Vec3 &p, Vec3 &n, Float &pdf) const {
surface->sample(rd, p, n, pdf);
}
inline void AreaLight::sample(Random &rd, Vec3 &p, Vec3 &n, Float &pdf, const Receiver &patch) const {
surface->sample(rd, p, n, pdf, patch);
}
inline void AreaLight::sample(Random &rd, Vec3 &p, Vec3 &n, Vec3 &wo, Rgb &radiance, Float &pdf) const {
Float pdf_p;
Float pdf_wo;
this->sample(rd, p, n, wo, radiance, pdf_p, pdf_wo);
pdf = pdf_p * pdf_wo;
}
inline Float AreaLight::pdf(const Vec3 &p, const Receiver &patch) const {
return surface->pdf(p, patch);
}
inline Float AreaLight::pdf(const Vec3 &p) const {
return surface->pdf(p);
}
inline Float AreaLight::pdf(const Vec3 &p, const Vec3 &n, const Vec3 &wo) const {
if (dot(wo, n) < ZERO_EPSILON) return 0.0f;
Float pdf_p = surface->pdf(p);
Float pdf_wo;
if (pdf_p <= 0.0f)
pdf_wo = 0.0f;
else
pdf_wo = dot(wo, n) * INV_PI;
return pdf_p * pdf_wo;
}
inline void AreaLight::pdf(const Vec3 &p, const Vec3 &n, const Vec3 &wo, Float &pdf_p, Float &pdf_wo) const {
if (dot(wo, n) < ZERO_EPSILON) {
pdf_p = 0.0f;
pdf_wo = 0.0f;
} else {
pdf_p = surface->pdf(p);
if (pdf_p <= 0.0f)
pdf_wo = 0.0f;
else
pdf_wo = dot(wo, n) * INV_PI;
}
}
inline Float AreaLight::pdf_wo(const Vec3 &p, const Vec3 &wo) const {
Vec3 n = surface->get_shape()->shading_normal(p);
return std::max(dot(wo, n) * INV_PI, 0.0f);
}
} // end namespace Renzoku
#endif