erebus

annotate liberebus/src/brdf.h @ 31:53a98c148bf8

- introduced SurfaceGeometry to carry all the geometric information input to BRDF sampling and evaluation functions. - made Reflectance keep an (optional) pointer to its material - simplified PhongRefl::sample_dir, with the help of SurfaceGeometry - worked around microsoft's broken std::thread implementation's deadlock on join
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 07 Jun 2014 09:14:17 +0300
parents 4a0a288ffb27
children c4d48a21bc4a
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_