-
Notifications
You must be signed in to change notification settings - Fork 1
/
texture.h
127 lines (95 loc) · 2.91 KB
/
texture.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
#ifndef TEXTURE_H
#define TEXTURE_H
#include "rtweekend.h"
#include "perlin.h"
#include "rtw_stb_image.h"
#include <iostream>
class texture {
public:
virtual color value(double u, double v, const point3& p) const = 0;
};
class solid_color : public texture {
public:
solid_color() {}
solid_color(color c) : color_value(c) {}
solid_color(double red, double green, double blue)
: solid_color(color(red,green,blue)) {}
virtual color value(double u, double v, const vec3& p) const override {
return color_value;
}
private:
color color_value;
};
class checker_texture : public texture {
public:
checker_texture() {}
checker_texture(shared_ptr<texture> _even, shared_ptr<texture> _odd)
: even(_even), odd(_odd) {}
checker_texture(color c1, color c2)
: even(make_shared<solid_color>(c1)), odd(make_shared<solid_color>(c2)) {}
virtual color value(double u, double v, const point3& p) const override {
auto sines = sin(10*p.x())*sin(10*p.z());
if (sines < 0)
return odd->value(u, v, p);
else
return even->value(u, v, p);
}
public:
shared_ptr<texture> odd;
shared_ptr<texture> even;
};
class noise_texture : public texture {
public:
noise_texture() {}
noise_texture(double sc) : scale(sc) {}
virtual color value(double u, double v, const point3& p) const override {
return color(1,1,1) * 0.5 * (1 + sin(scale*p.z() + 10*noise.turb(p)));
}
public:
perlin noise;
double scale;
};
class image_texture : public texture {
public:
const static int bytes_per_pixel = 3;
image_texture()
: data(nullptr), width(0), height(0), bytes_per_scanline(0) {}
image_texture(const char* filename) {
auto components_per_pixel = bytes_per_pixel;
data = stbi_load(
filename, &width, &height, &components_per_pixel, components_per_pixel);
if (!data) {
std::cerr << "ERROR: Could not load texture image file '" << filename << "'.\n";
width = height = 0;
}
bytes_per_scanline = bytes_per_pixel * width;
}
~image_texture() {
delete data;
}
virtual color value(double u, double v, const vec3& p) const override {
// If we have no texture data, then return solid cyan as a debugging aid.
if (data == nullptr)
return color(0,1,1);
// Clamp input texture coordinates to [0,1] x [1,0]
u = clamp(u, 0.0, 1.0);
v = 1.0 - clamp(v, 0.0, 1.0); // Flip V to image coordinates
auto i = static_cast<int>(u * width);
auto j = static_cast<int>(v * height);
// Clamp integer mapping, since actual coordinates should be less than 1.0
if (i >= width){
i = width-1;
}
if (j >= height){
j = height-1;
}
const auto color_scale = 1.0 / 255.0;
auto pixel = data + j*bytes_per_scanline + i*bytes_per_pixel;
return color(color_scale*pixel[0], color_scale*pixel[1], color_scale*pixel[2]);
}
private:
unsigned char *data;
int width, height;
int bytes_per_scanline;
};
#endif