gpuray_glsl

view src/texture.cc @ 0:f234630e38ff

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 09 Nov 2014 13:03:36 +0200
parents
children 92695e89164b
line source
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <string.h>
4 #include <errno.h>
5 #include "texture.h"
6 #include "object.h"
8 static inline Color sample_image(const Image &img, float u, float v, Texture::WrapMode wrapping);
10 Texture::Texture()
11 : sampling(SampleMode::nearest), wrapping(WrapMode::repeat)
12 {
13 }
15 Texture::~Texture() {}
17 void Texture::set_name(const char *name)
18 {
19 this->name = name;
20 }
22 const char *Texture::get_name() const
23 {
24 return name.c_str();
25 }
27 void Texture::set_sampling_mode(SampleMode mode)
28 {
29 sampling = mode;
30 }
32 Texture::SampleMode Texture::get_sampling_mode() const
33 {
34 return sampling;
35 }
37 void Texture::set_wrapping_mode(WrapMode mode)
38 {
39 wrapping = mode;
40 }
42 Texture::WrapMode Texture::get_wrapping_mode() const
43 {
44 return wrapping;
45 }
48 Color Texture::sample(const HitPoint &hit) const
49 {
50 return sample(hit.texcoord.x, hit.texcoord.y, 0.0f);
51 }
53 Image *Texture2D::get_image(int idx)
54 {
55 return &img;
56 }
58 const Image *Texture2D::get_image(int idx) const
59 {
60 return &img;
61 }
64 bool Texture2D::load(const char *fname)
65 {
66 name = fname;
67 return img.load(fname);
68 }
70 Color Texture2D::sample(float u, float v, float w) const
71 {
72 return sample_image(img, u, v, wrapping);
73 }
75 TextureCube::TextureCube()
76 {
77 wrapping = WrapMode::clamp;
78 }
80 Image *TextureCube::get_image(int idx)
81 {
82 return &img[idx];
83 }
85 const Image *TextureCube::get_image(int idx) const
86 {
87 return &img[idx];
88 }
91 bool TextureCube::load(const char *fname)
92 {
93 // assume it's a cubemap descriptor file (face path per line)
94 FILE *fp;
95 if(!(fp = fopen(fname, "r"))) {
96 fprintf(stderr, "failed to open the cubemap descriptor %s: %s\n", fname, strerror(errno));
97 return false;
98 }
100 name = fname;
102 char *prefix = (char*)alloca(strlen(fname) + 1);
103 strcpy(prefix, fname);
104 char *ptr = strrchr(prefix, '/');
105 if(!ptr) {
106 ptr = prefix;
107 }
108 *ptr = 0;
110 int xsz = 0, ysz = 0;
112 // load the faces
113 char buf[512];
114 for(int i=0; i<6; i++) {
115 if(!fgets(buf, sizeof buf, fp)) {
116 fprintf(stderr, "invalid cubemap descriptor file: %s\n", fname);
117 return false;
118 }
119 if(buf[strlen(buf) - 1] == '\n') {
120 buf[strlen(buf) - 1] = 0;
121 }
123 std::string path = std::string(prefix) + "/" + std::string(buf);
124 if(!img[i].load(path.c_str())) {
125 fprintf(stderr, "failed to load image: %s\n", path.c_str());
126 fclose(fp);
127 return false;
128 }
130 if(i == 0) {
131 xsz = img[i].xsz;
132 ysz = img[i].ysz;
133 } else {
134 if(img[i].xsz != xsz || img[i].ysz != ysz) {
135 fprintf(stderr, "cubemap %s face image %s size (%dx%d) doesn't match the previous faces (%dx%d)\n",
136 fname, path.c_str(), img[i].xsz, img[i].ysz, xsz, ysz);
137 fclose(fp);
138 return false;
139 }
140 }
141 }
142 return true;
143 }
145 Color TextureCube::sample(float u, float v, float w) const
146 {
147 int face;
148 Vector2 uv;
150 float abs_u = fabs(u);
151 float abs_v = fabs(v);
152 float abs_w = fabs(w);
154 if(abs_u > abs_v && abs_u > abs_w) {
155 if(u >= 0.0) {
156 face = 0;
157 uv.x = w / abs_u;
158 uv.y = v / abs_u;
159 } else {
160 face = 1;
161 uv.x = -w / abs_u;
162 uv.y = v / abs_u;
163 }
164 } else if(abs_v > abs_w) {
165 if(v >= 0.0) {
166 face = 2;
167 uv.x = u / abs_v;
168 uv.y = w / abs_v;
169 } else {
170 face = 3;
171 uv.x = u / abs_v;
172 uv.y = -w / abs_v;
173 }
174 } else {
175 if(w >= 0.0) {
176 face = 5;
177 uv.x = -u / abs_w;
178 uv.y = v / abs_w;
179 } else {
180 face = 4;
181 uv.x = u / abs_w;
182 uv.y = v / abs_w;
183 }
184 }
186 return sample_image(img[face], uv.x * 0.5 + 0.5, uv.y * 0.5 + 0.5, wrapping);
187 }
189 Color TextureCube::sample(const HitPoint &hit) const
190 {
191 return sample(hit.normal.x, hit.normal.y, hit.normal.z);
192 }
194 Texture *load_texture(const char *fname)
195 {
196 if(access(fname, R_OK) == -1) {
197 fprintf(stderr, "failed to load texture %s: %s\n", fname, strerror(errno));
198 return 0;
199 }
201 Texture2D *tex2d = new Texture2D;
202 if(tex2d->load(fname)) {
203 return tex2d;
204 }
205 delete tex2d;
207 TextureCube *texcube = new TextureCube;
208 if(texcube->load(fname)) {
209 return texcube;
210 }
211 delete texcube;
213 return 0;
214 }
216 #define CLAMP(x, lo, hi) ((x) < (lo) ? (lo) : ((x) > (hi) ? (hi) : (x)))
218 static inline Color sample_image(const Image &img, float u, float v, Texture::WrapMode wrapping)
219 {
220 int x = (int)round(u * img.xsz);
221 int y = (int)round((1.0 - v) * img.ysz);
223 if(wrapping == Texture::WrapMode::clamp) {
224 x = CLAMP(x, 0, img.xsz - 1);
225 y = CLAMP(y, 0, img.ysz - 1);
226 } else {
227 x %= img.xsz;
228 y %= img.ysz;
230 if(x < 0)
231 x += img.xsz;
232 if(y < 0)
233 y += img.ysz;
234 }
236 return img.pixels[y * img.xsz + x];
237 }