gpuray_glsl

view src/texture.cc @ 1:92695e89164b

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