rev |
line source |
nuclear@2
|
1 #ifndef BRDF_H_
|
nuclear@2
|
2 #define BRDF_H_
|
nuclear@2
|
3
|
nuclear@21
|
4 #include <vector>
|
nuclear@2
|
5 #include "texture.h"
|
nuclear@2
|
6
|
nuclear@31
|
7 class Material;
|
nuclear@31
|
8
|
nuclear@31
|
9 class SurfaceGeometry {
|
nuclear@31
|
10 public:
|
nuclear@31
|
11 Vector3 normal, tangent;
|
nuclear@31
|
12 Vector2 uv;
|
nuclear@31
|
13
|
nuclear@31
|
14 enum VecLength { unit, unknown };
|
nuclear@31
|
15
|
nuclear@31
|
16 explicit SurfaceGeometry(const Vector3 &norm, VecLength st = unknown);
|
nuclear@31
|
17 SurfaceGeometry(const Vector3 &norm, const Vector2 &uv, VecLength st = unknown);
|
nuclear@31
|
18 SurfaceGeometry(const Vector3 &norm, const Vector3 &tang, VecLength st = unknown);
|
nuclear@31
|
19 SurfaceGeometry(const Vector3 &norm, const Vector3 &tang, const Vector2 &uv, VecLength st = unknown);
|
nuclear@31
|
20
|
nuclear@31
|
21 /** create a cartesian direction vector in sample space (zenith = +Z) and
|
nuclear@31
|
22 * transform it to world space.
|
nuclear@31
|
23 * \param theta the horizontal angle (azimuth, in radians) around the Z axis [0, 2pi]
|
nuclear@31
|
24 * \param phi the vertical angle (elevation, in radians) away from the Z axis [0, pi]
|
nuclear@31
|
25 */
|
nuclear@31
|
26 Vector3 spherical_to_world(float theta, float phi) const;
|
nuclear@31
|
27 /// transforms a direction vector from sample space (centered around Z) to world space
|
nuclear@31
|
28 Vector3 sample_to_world(const Vector3 &v) const;
|
nuclear@31
|
29 /// transforms a direction vector from world space to sample space (centered around Z)
|
nuclear@31
|
30 Vector3 world_to_sample(const Vector3 &v) const;
|
nuclear@31
|
31 };
|
nuclear@31
|
32
|
nuclear@31
|
33 /// abstract bidirection reflectance distribution function base class
|
nuclear@2
|
34 class Reflectance {
|
nuclear@31
|
35 protected:
|
nuclear@31
|
36 const Material *mtl; // pointer to the material we belong to
|
nuclear@31
|
37
|
nuclear@2
|
38 public:
|
nuclear@2
|
39 Reflectance();
|
nuclear@31
|
40 explicit Reflectance(const Material *mtl);
|
nuclear@2
|
41 virtual ~Reflectance() = default;
|
nuclear@2
|
42
|
nuclear@31
|
43 void set_material(const Material *mtl);
|
nuclear@31
|
44 const Material *get_material() const;
|
nuclear@31
|
45
|
nuclear@31
|
46 /// given an outgoing light direction generate an incidence direction to sample the BRDF
|
nuclear@31
|
47 virtual Vector3 sample_dir(const SurfaceGeometry &geom, const Vector3 &outdir) const = 0;
|
nuclear@31
|
48 /// given an outgoing direction, generate an incidence direction, and evaluate its probability
|
nuclear@31
|
49 virtual float sample(const SurfaceGeometry &geom, const Vector3 &outdir, Vector3 *indir) const;
|
nuclear@31
|
50 /// given an outgoing direction and an incidence direction, evaluate the probability of this path
|
nuclear@31
|
51 virtual float eval(const SurfaceGeometry &geom, const Vector3 &outdir, const Vector3 &indir) const = 0;
|
nuclear@2
|
52 };
|
nuclear@2
|
53
|
nuclear@31
|
54 typedef float (*CompReflWeightFunc)(const SurfaceGeometry &geom, const Vector3 &outdir);
|
nuclear@21
|
55
|
nuclear@31
|
56 /// composite BRDF, with multiple weighted sub-reflectances.
|
nuclear@21
|
57 class CompositeRefl : public Reflectance {
|
nuclear@21
|
58 private:
|
nuclear@21
|
59 struct SubRefl {
|
nuclear@21
|
60 Reflectance *brdf;
|
nuclear@21
|
61 float weight;
|
nuclear@21
|
62 CompReflWeightFunc weight_func; // if null, use static weight above
|
nuclear@21
|
63 };
|
nuclear@21
|
64 std::vector<SubRefl> sub_brdf;
|
nuclear@21
|
65 mutable bool valid_checked;
|
nuclear@21
|
66
|
nuclear@31
|
67 int pick_brdf(const SurfaceGeometry &geom, const Vector3 &outdir) const;
|
nuclear@21
|
68
|
nuclear@21
|
69 public:
|
nuclear@21
|
70 CompositeRefl();
|
nuclear@31
|
71 explicit CompositeRefl(const Material *mtl);
|
nuclear@21
|
72
|
nuclear@21
|
73 virtual void add_brdf(Reflectance *brdf, float weight);
|
nuclear@21
|
74 virtual void add_brdf(Reflectance *brdf, CompReflWeightFunc weight_func);
|
nuclear@21
|
75
|
nuclear@21
|
76 bool check_valid() const;
|
nuclear@21
|
77
|
nuclear@31
|
78 Vector3 sample_dir(const SurfaceGeometry &geom, const Vector3 &outdir) const override;
|
nuclear@31
|
79 float sample(const SurfaceGeometry &geom, const Vector3 &outdir, Vector3 *indir) const override;
|
nuclear@31
|
80 float eval(const SurfaceGeometry &geom, const Vector3 &outdir, const Vector3 &indir) const override;
|
nuclear@21
|
81 };
|
nuclear@21
|
82
|
nuclear@31
|
83 /// lambertian perfect diffuse reflectance
|
nuclear@2
|
84 class LambertRefl : public Reflectance {
|
nuclear@2
|
85 public:
|
nuclear@31
|
86 Vector3 sample_dir(const SurfaceGeometry &geom, const Vector3 &outdir) const override;
|
nuclear@31
|
87 float eval(const SurfaceGeometry &geom, const Vector3 &outdir, const Vector3 &indir) const override;
|
nuclear@2
|
88 };
|
nuclear@2
|
89
|
nuclear@31
|
90 /// perfect specular reflectance
|
nuclear@21
|
91 class MirrorRefl : public Reflectance {
|
nuclear@21
|
92 public:
|
nuclear@31
|
93 Vector3 sample_dir(const SurfaceGeometry &geom, const Vector3 &outdir) const override;
|
nuclear@31
|
94 float eval(const SurfaceGeometry &geom, const Vector3 &outdir, const Vector3 &indir) const override;
|
nuclear@21
|
95 };
|
nuclear@21
|
96
|
nuclear@31
|
97 /// glossy phong reflectance with lafortune sampling
|
nuclear@28
|
98 class PhongRefl : public Reflectance {
|
nuclear@28
|
99 public:
|
nuclear@31
|
100 Vector3 sample_dir(const SurfaceGeometry &geom, const Vector3 &outdir) const override;
|
nuclear@31
|
101 float eval(const SurfaceGeometry &geom, const Vector3 &outdir, const Vector3 &indir) const override;
|
nuclear@28
|
102 };
|
nuclear@28
|
103
|
nuclear@2
|
104 #endif // BRDF_H_
|