# HG changeset patch # User John Tsiombikas # Date 1384669213 -7200 # Node ID 3d96734fd47746e48c777a2315c28a3d34cd902d # Parent 18879c956eb1750139d314b07915140f932eda3c cubemap loading and cubemap example program diff -r 18879c956eb1 -r 3d96734fd477 examples/cubemap/data/cubemap2.jpg Binary file examples/cubemap/data/cubemap2.jpg has changed diff -r 18879c956eb1 -r 3d96734fd477 examples/cubemap/sdr/sky.p.glsl --- a/examples/cubemap/sdr/sky.p.glsl Sun Nov 17 03:22:40 2013 +0200 +++ b/examples/cubemap/sdr/sky.p.glsl Sun Nov 17 08:20:13 2013 +0200 @@ -5,4 +5,5 @@ void main() { gl_FragColor = textureCube(cubemap, norm); + //gl_FragColor = vec4(norm * 0.5 + 0.5, 1.0); } diff -r 18879c956eb1 -r 3d96734fd477 examples/cubemap/sdr/sky.v.glsl --- a/examples/cubemap/sdr/sky.v.glsl Sun Nov 17 03:22:40 2013 +0200 +++ b/examples/cubemap/sdr/sky.v.glsl Sun Nov 17 08:20:13 2013 +0200 @@ -3,5 +3,5 @@ void main() { gl_Position = ftransform(); - norm = gl_NormalMatrix * gl_Normal; + norm = gl_Vertex.xyz; } diff -r 18879c956eb1 -r 3d96734fd477 examples/cubemap/src/main.cc --- a/examples/cubemap/src/main.cc Sun Nov 17 03:22:40 2013 +0200 +++ b/examples/cubemap/src/main.cc Sun Nov 17 08:20:13 2013 +0200 @@ -4,7 +4,7 @@ #include #include -#define CUBEMAP_FILENAME "data/cubemap3.jpg" +#define CUBEMAP_FILENAME "data/cubemap2.jpg" static bool init(); static void cleanup(); @@ -79,16 +79,7 @@ setup_gl_matrices(); - skybox(); - - /*glBegin(GL_QUADS); - glColor3f(1, 1, 1); - glNormal3f(0, 1, 0); - glVertex3f(-0.8, -1, 0.8); - glVertex3f(0.8, -1, 0.8); - glVertex3f(0.8, -1, -0.8); - glVertex3f(-0.8, -1, -0.8); - glEnd();*/ + skybox(cubemap); glutSwapBuffers(); CHECKGLERR; @@ -96,52 +87,24 @@ static void skybox(const TextureCube *cubemap) { + static Mesh *skybox; + + if(!skybox) { + skybox = new Mesh; + gen_sphere(skybox, 10.0, 12, 6); + } + glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_CUBE_MAP); + if(cubemap) cubemap->bind(); sdrsky->bind(); - glBegin(GL_QUADS); - // +X - glColor3f(1, 0, 0); - glVertex3f(1, -1, 1); - glVertex3f(1, -1, -1); - glVertex3f(1, 1, -1); - glVertex3f(1, 1, 1); - // -Z - glColor3f(0, 1, 0); - glVertex3f(1, -1, -1); - glVertex3f(-1, -1, -1); - glVertex3f(-1, 1, -1); - glVertex3f(1, 1, -1); - // -X - glColor3f(0, 0, 1); - glVertex3f(-1, -1, -1); - glVertex3f(-1, -1, 1); - glVertex3f(-1, 1, 1); - glVertex3f(-1, 1, -1); - // +Z - glColor3f(1, 1, 0); - glVertex3f(-1, -1, 1); - glVertex3f(1, -1, 1); - glVertex3f(1, 1, 1); - glVertex3f(-1, 1, 1); - // +Y - glColor3f(0, 1, 1); - glVertex3f(-1, 1, 1); - glVertex3f(1, 1, 1); - glVertex3f(1, 1, -1); - glVertex3f(-1, 1, -1); - // -Y - glColor3f(1, 0, 1); - glVertex3f(-1, -1, -1); - glVertex3f(1, -1, -1); - glVertex3f(1, -1, 1); - glVertex3f(-1, -1, 1); - glEnd(); + skybox->draw(); glUseProgram(0); glPopAttrib(); diff -r 18879c956eb1 -r 3d96734fd477 src/image.cc --- a/src/image.cc Sun Nov 17 03:22:40 2013 +0200 +++ b/src/image.cc Sun Nov 17 08:20:13 2013 +0200 @@ -1,4 +1,11 @@ #include + +#ifndef _MSC_VER +#include +#else +#include +#endif + #include "imago2.h" #include "image.h" #include "logger.h" @@ -50,12 +57,39 @@ return true; } -bool Image::set_pixels(int x, int y, void *pixels, Format fmt) +bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt) { - if(!create(x, y, fmt)) { + if(!create(xsz, ysz, fmt)) { return false; } - memcpy(this->pixels, pixels, x * y * pixel_size(fmt)); + memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt)); + return true; +} + +bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt) +{ + return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt); +} + +bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt) +{ + if(scan_width <= 0) { + scan_width = xsz; + } + + if(!create(xsz, ysz, fmt)) { + return false; + } + + int pixsz = pixel_size(fmt); + + unsigned char *dest = (unsigned char*)this->pixels; + unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz; + for(int i=0; i dest) { + memcpy(tmppix, src, pixsz); + memcpy(src, dest, pixsz); + memcpy(dest, tmppix, pixsz); + dest += pixsz; + src -= pixsz; + } + + scan += width * pixsz; + } +} + +void Image::flip_vertical() +{ + int pixsz = pixel_size(fmt); + + unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz); + + unsigned char *dest = (unsigned char*)pixels; + unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz; + + while(src > dest) { + memcpy(tmpscan, src, width * pixsz); + memcpy(src, dest, width * pixsz); + memcpy(dest, tmpscan, width * pixsz); + dest += width * pixsz; + src -= width * pixsz; + } +} + +void Image::rotate_180() +{ + flip_vertical(); + flip_horizontal(); +} + bool Image::load(const char *fname) { struct img_pixmap pixmap; diff -r 18879c956eb1 -r 3d96734fd477 src/image.h --- a/src/image.h Sun Nov 17 03:22:40 2013 +0200 +++ b/src/image.h Sun Nov 17 08:20:13 2013 +0200 @@ -28,9 +28,15 @@ Format get_format() const; bool create(int x, int y, Format fmt = FMT_RGBA); - bool set_pixels(int x, int y, void *pixels, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt = FMT_RGBA); + bool set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width = -1, Format fmt = FMT_RGBA); void *get_pixels() const; + void flip_horizontal(); + void flip_vertical(); + void rotate_180(); + bool load(const char *fname); bool save(const char *fname) const; }; diff -r 18879c956eb1 -r 3d96734fd477 src/texture.cc --- a/src/texture.cc Sun Nov 17 03:22:40 2013 +0200 +++ b/src/texture.cc Sun Nov 17 08:20:13 2013 +0200 @@ -245,10 +245,10 @@ texfmt = ifmt; glBindTexture(GL_TEXTURE_CUBE_MAP, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); for(int i=0; i<6; i++) { glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); @@ -257,12 +257,56 @@ void TextureCube::set_image(const Image &img, int idx) { - // TODO + texfmt = glifmt_from_imgfmt(img.get_format()); + unsigned int fmt = glfmt_from_ifmt(texfmt); + unsigned int type = gltype_from_ifmt(texfmt); + + sz[0] = img.get_width(); + sz[1] = img.get_height(); + + glBindTexture(GL_TEXTURE_CUBE_MAP, id); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); } bool TextureCube::load(const char *fname) { - return false; // TODO + static const float one_third = 1.0 / 3.0; + static const float two_thirds = 2.0 / 3.0; + static const float hcross[2][6] = { + {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} }; + static const float vcross[2][6] = { + {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} }; + static const float hsix[2][6] = { + {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} }; + + Image img; + if(!img.load(fname)) { + return false; + } + + int xsz = img.get_width(); + int ysz = img.get_height(); + + if(xsz / 4 == ysz / 3) { + // horizontal cross, assume the vertical bit is center-left + return load_multi(img, hcross[0], hcross[1], xsz / 4); + } + if(xsz / 3 == ysz / 4) { + // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) + return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); + } + if(xsz / 3 == ysz / 2) { + // horizontal sixpack + return load_multi(img, hsix[0], hsix[1], ysz / 2); + } + + error_log("failed to load %s: unknown cubemap configuration\n", fname); + return false; } bool TextureCube::save(const char *fname) const @@ -270,6 +314,27 @@ return false; // TODO } +bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, + unsigned int rotmask) +{ + for(int i=0; i<6; i++) { + Image face; + + int xoffs = xoffsets[i] * img.get_width(); + int yoffs = yoffsets[i] * img.get_height(); + + if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) { + return false; + } + + if(rotmask & (1 << i)) { + face.rotate_180(); + } + set_image(face, i); + } + return true; +} + static int glifmt_from_ifmt(unsigned int ifmt) { #ifdef GL_ES_VERSION_2_0 diff -r 18879c956eb1 -r 3d96734fd477 src/texture.h --- a/src/texture.h Sun Nov 17 03:22:40 2013 +0200 +++ b/src/texture.h Sun Nov 17 08:20:13 2013 +0200 @@ -51,6 +51,10 @@ }; class TextureCube : public Texture { +private: + bool load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, + unsigned int rotmask = 0); + public: TextureCube();