Path Tracer
texture.hpp
1 #pragma once
2 //
3 #include <color/spectrum.hpp>
4 #include <common.hpp>
5 #include <texture/perlin.hpp>
6 #include <camera/ray.hpp>
7 #include <math3d/vec3.hpp>
8 using namespace ptracey;
9 namespace ptracey {
10 class texture {
11 public:
12  virtual color value(Real u, Real v, const vec3 &p,
13  const WaveLength &w) const = 0;
14 };
15 class solid_color : public texture {
16 public:
17  solid_color() {}
18  solid_color(const spectrum &c) : color_value(c) {}
19 
20  solid_color(Real red, Real green, Real blue)
21  : solid_color(spectrum(red, green, blue)) {}
22 
23  color value(Real u, Real v, const vec3 &p,
24  const WaveLength &w) const override {
25  return color_value.evaluate(w);
26  }
27 
28 private:
29  spectrum color_value;
30 };
31 class checker_texture : public texture {
32 public:
33  checker_texture() {}
34 
35  checker_texture(shared_ptr<texture> _odd,
36  shared_ptr<texture> _even)
37  : odd(_odd), even(_even) {}
38 
39  checker_texture(const spectrum &c1, const spectrum &c2)
40  : odd(make_shared<solid_color>(c1)),
41  even(make_shared<solid_color>(c2)) {}
42 
43  color value(Real u, Real v, const vec3 &p,
44  const WaveLength &w) const override {
45  auto sines =
46  sin(10 * p.x()) * sin(10 * p.y()) * sin(10 * p.z());
47  if (sines < 0)
48  return odd->value(u, v, p, w);
49  else
50  return even->value(u, v, p, w);
51  }
52 
53 public:
54  shared_ptr<texture> odd;
55  shared_ptr<texture> even;
56 };
57 class noise_texture : public texture {
58 public:
59  noise_texture() {}
60  noise_texture(Real sc, const spectrum &sp)
61  : scale(sc), spec(sp) {}
62 
63  color value(Real u, Real v, const vec3 &p,
64  const WaveLength &w) const override {
65  Real coeff =
66  0.5 * (1 + sin(scale * p.z() + 10 * noise.turb(p)));
67  color eval = spec.evaluate(w);
68  eval *= coeff;
69  return eval;
70  }
71 
72 public:
73  perlin noise;
74  Real scale;
75  spectrum spec;
76 };
77 class image_texture : public texture {
78 public:
79  const static int bytes_per_pixel = 3;
81  : data(nullptr), width(0), height(0),
82  bytes_per_scanline(0) {}
83  image_texture(const char *filename) {
84  auto components_per_pixel = bytes_per_pixel;
85 
86  data = stbi_load(filename, &width, &height,
87  &components_per_pixel,
88  components_per_pixel);
89 
90  if (!data) {
91  std::cerr
92  << "ERROR: Could not load texture image file '"
93  << filename << "'.\n";
94  width = height = 0;
95  }
96 
97  bytes_per_scanline = bytes_per_pixel * width;
98  }
99  ~image_texture() { STBI_FREE(data); }
100  color value(Real u, Real v, const vec3 &p,
101  const WaveLength &wl) const override {
102  // If we have no texture data, then return solid cyan as
103  // a debugging aid.
104  if (data == nullptr) {
105  return spectrum(0, 1, 1).evaluate(wl);
106  }
107 
108  // Clamp input texture coordinates to [0,1] x [1,0]
109  u = clamp(u, 0.0, 1.0);
110  v = 1.0 -
111  clamp(v, 0.0, 1.0); // Flip V to image coordinates
112 
113  auto i = static_cast<int>(u * width);
114  auto j = static_cast<int>(v * height);
115 
116  // Clamp integer mapping, since actual coordinates
117  // should be less than 1.0
118  if (i >= width)
119  i = width - 1;
120  if (j >= height)
121  j = height - 1;
122 
123  const auto color_scale = 1.0 / 255.0;
124  auto pixel =
125  data + j * bytes_per_scanline + i * bytes_per_pixel;
126 
127  spectrum pix_rgb(color_scale * pixel[0],
128  color_scale * pixel[1],
129  color_scale * pixel[2]);
130  return pix_rgb.evaluate(wl);
131  }
132 
133 private:
134  unsigned char *data;
135  int width, height;
136  int bytes_per_scanline;
137 };
138 class material_texture : public texture {
139  // use material refractive spectral power distribution
140  // for color
141 public:
142  material_texture(const spectrum &s)
143  : spect(make_shared<solid_color>(s)) {}
144  material_texture(shared_ptr<texture> t) : spect(t) {}
146  const path &path_to_csv,
147  const std::string &wave_col_name,
148  const std::string &power_col_name,
149  const char &sep = ',',
150  const unsigned int stride = SPD_STRIDE,
151  SpectrumType stype = SpectrumType::Reflectance) {
152  auto spd_material =
153  spectrum(CSV_PARENT / path_to_csv, wave_col_name,
154  power_col_name, sep, stride, stype);
155  spect = make_shared<solid_color>(spd_material);
156  }
157 
158  color value(Real u, Real v, const vec3 &p,
159  const WaveLength &w) const {
160  return spect->value(u, v, p, w);
161  }
162 
163 public:
164  shared_ptr<texture> spect;
165 };
166 }
ptracey::solid_color
Definition: texture.hpp:15
ptracey::image_texture
Definition: texture.hpp:77
ptracey::texture
Definition: texture.hpp:10
ptracey::checker_texture
Definition: texture.hpp:31
ptracey::perlin
Definition: perlin.hpp:9
ptracey::vec3
Definition: vec3.hpp:7
ptracey::material_texture
Definition: texture.hpp:138
ptracey::sampled_spectrum
Definition: sampled_spectrum.hpp:126
ptracey::noise_texture
Definition: texture.hpp:57
ptracey::color
Definition: color.hpp:9