gpuray_glsl

annotate src/texture.cc @ 2:6e3a4daf3159

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