goat3dgfx
changeset 6:3d96734fd477
cubemap loading and cubemap example program
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 17 Nov 2013 08:20:13 +0200 |
parents | 18879c956eb1 |
children | 89179bce7543 |
files | examples/cubemap/data/cubemap2.jpg examples/cubemap/sdr/sky.p.glsl examples/cubemap/sdr/sky.v.glsl examples/cubemap/src/main.cc src/image.cc src/image.h src/texture.cc src/texture.h |
diffstat | 8 files changed, 180 insertions(+), 60 deletions(-) [+] |
line diff
1.1 Binary file examples/cubemap/data/cubemap2.jpg has changed
2.1 --- a/examples/cubemap/sdr/sky.p.glsl Sun Nov 17 03:22:40 2013 +0200 2.2 +++ b/examples/cubemap/sdr/sky.p.glsl Sun Nov 17 08:20:13 2013 +0200 2.3 @@ -5,4 +5,5 @@ 2.4 void main() 2.5 { 2.6 gl_FragColor = textureCube(cubemap, norm); 2.7 + //gl_FragColor = vec4(norm * 0.5 + 0.5, 1.0); 2.8 }
3.1 --- a/examples/cubemap/sdr/sky.v.glsl Sun Nov 17 03:22:40 2013 +0200 3.2 +++ b/examples/cubemap/sdr/sky.v.glsl Sun Nov 17 08:20:13 2013 +0200 3.3 @@ -3,5 +3,5 @@ 3.4 void main() 3.5 { 3.6 gl_Position = ftransform(); 3.7 - norm = gl_NormalMatrix * gl_Normal; 3.8 + norm = gl_Vertex.xyz; 3.9 }
4.1 --- a/examples/cubemap/src/main.cc Sun Nov 17 03:22:40 2013 +0200 4.2 +++ b/examples/cubemap/src/main.cc Sun Nov 17 08:20:13 2013 +0200 4.3 @@ -4,7 +4,7 @@ 4.4 #include <goat3dgfx/goat3dgfx.h> 4.5 #include <vmath/vmath.h> 4.6 4.7 -#define CUBEMAP_FILENAME "data/cubemap3.jpg" 4.8 +#define CUBEMAP_FILENAME "data/cubemap2.jpg" 4.9 4.10 static bool init(); 4.11 static void cleanup(); 4.12 @@ -79,16 +79,7 @@ 4.13 4.14 setup_gl_matrices(); 4.15 4.16 - skybox(); 4.17 - 4.18 - /*glBegin(GL_QUADS); 4.19 - glColor3f(1, 1, 1); 4.20 - glNormal3f(0, 1, 0); 4.21 - glVertex3f(-0.8, -1, 0.8); 4.22 - glVertex3f(0.8, -1, 0.8); 4.23 - glVertex3f(0.8, -1, -0.8); 4.24 - glVertex3f(-0.8, -1, -0.8); 4.25 - glEnd();*/ 4.26 + skybox(cubemap); 4.27 4.28 glutSwapBuffers(); 4.29 CHECKGLERR; 4.30 @@ -96,52 +87,24 @@ 4.31 4.32 static void skybox(const TextureCube *cubemap) 4.33 { 4.34 + static Mesh *skybox; 4.35 + 4.36 + if(!skybox) { 4.37 + skybox = new Mesh; 4.38 + gen_sphere(skybox, 10.0, 12, 6); 4.39 + } 4.40 + 4.41 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT); 4.42 glDisable(GL_DEPTH_TEST); 4.43 glDisable(GL_CULL_FACE); 4.44 glDisable(GL_LIGHTING); 4.45 4.46 + glEnable(GL_TEXTURE_CUBE_MAP); 4.47 + 4.48 if(cubemap) cubemap->bind(); 4.49 sdrsky->bind(); 4.50 4.51 - glBegin(GL_QUADS); 4.52 - // +X 4.53 - glColor3f(1, 0, 0); 4.54 - glVertex3f(1, -1, 1); 4.55 - glVertex3f(1, -1, -1); 4.56 - glVertex3f(1, 1, -1); 4.57 - glVertex3f(1, 1, 1); 4.58 - // -Z 4.59 - glColor3f(0, 1, 0); 4.60 - glVertex3f(1, -1, -1); 4.61 - glVertex3f(-1, -1, -1); 4.62 - glVertex3f(-1, 1, -1); 4.63 - glVertex3f(1, 1, -1); 4.64 - // -X 4.65 - glColor3f(0, 0, 1); 4.66 - glVertex3f(-1, -1, -1); 4.67 - glVertex3f(-1, -1, 1); 4.68 - glVertex3f(-1, 1, 1); 4.69 - glVertex3f(-1, 1, -1); 4.70 - // +Z 4.71 - glColor3f(1, 1, 0); 4.72 - glVertex3f(-1, -1, 1); 4.73 - glVertex3f(1, -1, 1); 4.74 - glVertex3f(1, 1, 1); 4.75 - glVertex3f(-1, 1, 1); 4.76 - // +Y 4.77 - glColor3f(0, 1, 1); 4.78 - glVertex3f(-1, 1, 1); 4.79 - glVertex3f(1, 1, 1); 4.80 - glVertex3f(1, 1, -1); 4.81 - glVertex3f(-1, 1, -1); 4.82 - // -Y 4.83 - glColor3f(1, 0, 1); 4.84 - glVertex3f(-1, -1, -1); 4.85 - glVertex3f(1, -1, -1); 4.86 - glVertex3f(1, -1, 1); 4.87 - glVertex3f(-1, -1, 1); 4.88 - glEnd(); 4.89 + skybox->draw(); 4.90 4.91 glUseProgram(0); 4.92 glPopAttrib();
5.1 --- a/src/image.cc Sun Nov 17 03:22:40 2013 +0200 5.2 +++ b/src/image.cc Sun Nov 17 08:20:13 2013 +0200 5.3 @@ -1,4 +1,11 @@ 5.4 #include <string.h> 5.5 + 5.6 +#ifndef _MSC_VER 5.7 +#include <alloca.h> 5.8 +#else 5.9 +#include <malloc.h> 5.10 +#endif 5.11 + 5.12 #include "imago2.h" 5.13 #include "image.h" 5.14 #include "logger.h" 5.15 @@ -50,12 +57,39 @@ 5.16 return true; 5.17 } 5.18 5.19 -bool Image::set_pixels(int x, int y, void *pixels, Format fmt) 5.20 +bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt) 5.21 { 5.22 - if(!create(x, y, fmt)) { 5.23 + if(!create(xsz, ysz, fmt)) { 5.24 return false; 5.25 } 5.26 - memcpy(this->pixels, pixels, x * y * pixel_size(fmt)); 5.27 + memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt)); 5.28 + return true; 5.29 +} 5.30 + 5.31 +bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt) 5.32 +{ 5.33 + return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt); 5.34 +} 5.35 + 5.36 +bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt) 5.37 +{ 5.38 + if(scan_width <= 0) { 5.39 + scan_width = xsz; 5.40 + } 5.41 + 5.42 + if(!create(xsz, ysz, fmt)) { 5.43 + return false; 5.44 + } 5.45 + 5.46 + int pixsz = pixel_size(fmt); 5.47 + 5.48 + unsigned char *dest = (unsigned char*)this->pixels; 5.49 + unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz; 5.50 + for(int i=0; i<ysz; i++) { 5.51 + memcpy(dest, src, xsz * pixsz); 5.52 + dest += xsz * pixsz; 5.53 + src += scan_width * pixsz; 5.54 + } 5.55 return true; 5.56 } 5.57 5.58 @@ -64,6 +98,53 @@ 5.59 return pixels; 5.60 } 5.61 5.62 +void Image::flip_horizontal() 5.63 +{ 5.64 + int pixsz = pixel_size(fmt); 5.65 + 5.66 + unsigned char *tmppix = (unsigned char*)alloca(pixsz); 5.67 + 5.68 + unsigned char *scan = (unsigned char*)pixels; 5.69 + for(int i=0; i<height; i++) { 5.70 + unsigned char *dest = scan; 5.71 + unsigned char *src = scan + (width - 1) * pixsz; 5.72 + 5.73 + while(src > dest) { 5.74 + memcpy(tmppix, src, pixsz); 5.75 + memcpy(src, dest, pixsz); 5.76 + memcpy(dest, tmppix, pixsz); 5.77 + dest += pixsz; 5.78 + src -= pixsz; 5.79 + } 5.80 + 5.81 + scan += width * pixsz; 5.82 + } 5.83 +} 5.84 + 5.85 +void Image::flip_vertical() 5.86 +{ 5.87 + int pixsz = pixel_size(fmt); 5.88 + 5.89 + unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz); 5.90 + 5.91 + unsigned char *dest = (unsigned char*)pixels; 5.92 + unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz; 5.93 + 5.94 + while(src > dest) { 5.95 + memcpy(tmpscan, src, width * pixsz); 5.96 + memcpy(src, dest, width * pixsz); 5.97 + memcpy(dest, tmpscan, width * pixsz); 5.98 + dest += width * pixsz; 5.99 + src -= width * pixsz; 5.100 + } 5.101 +} 5.102 + 5.103 +void Image::rotate_180() 5.104 +{ 5.105 + flip_vertical(); 5.106 + flip_horizontal(); 5.107 +} 5.108 + 5.109 bool Image::load(const char *fname) 5.110 { 5.111 struct img_pixmap pixmap;
6.1 --- a/src/image.h Sun Nov 17 03:22:40 2013 +0200 6.2 +++ b/src/image.h Sun Nov 17 08:20:13 2013 +0200 6.3 @@ -28,9 +28,15 @@ 6.4 Format get_format() const; 6.5 6.6 bool create(int x, int y, Format fmt = FMT_RGBA); 6.7 - bool set_pixels(int x, int y, void *pixels, Format fmt = FMT_RGBA); 6.8 + bool set_pixels(int xsz, int ysz, void *pixels, Format fmt = FMT_RGBA); 6.9 + bool set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt = FMT_RGBA); 6.10 + bool set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width = -1, Format fmt = FMT_RGBA); 6.11 void *get_pixels() const; 6.12 6.13 + void flip_horizontal(); 6.14 + void flip_vertical(); 6.15 + void rotate_180(); 6.16 + 6.17 bool load(const char *fname); 6.18 bool save(const char *fname) const; 6.19 };
7.1 --- a/src/texture.cc Sun Nov 17 03:22:40 2013 +0200 7.2 +++ b/src/texture.cc Sun Nov 17 08:20:13 2013 +0200 7.3 @@ -245,10 +245,10 @@ 7.4 texfmt = ifmt; 7.5 7.6 glBindTexture(GL_TEXTURE_CUBE_MAP, id); 7.7 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 7.8 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 7.9 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 7.10 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 7.11 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7.12 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 7.13 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 7.14 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 7.15 7.16 for(int i=0; i<6; i++) { 7.17 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 7.18 @@ -257,12 +257,56 @@ 7.19 7.20 void TextureCube::set_image(const Image &img, int idx) 7.21 { 7.22 - // TODO 7.23 + texfmt = glifmt_from_imgfmt(img.get_format()); 7.24 + unsigned int fmt = glfmt_from_ifmt(texfmt); 7.25 + unsigned int type = gltype_from_ifmt(texfmt); 7.26 + 7.27 + sz[0] = img.get_width(); 7.28 + sz[1] = img.get_height(); 7.29 + 7.30 + glBindTexture(GL_TEXTURE_CUBE_MAP, id); 7.31 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7.32 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 7.33 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 7.34 + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 7.35 + 7.36 + glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); 7.37 } 7.38 7.39 bool TextureCube::load(const char *fname) 7.40 { 7.41 - return false; // TODO 7.42 + static const float one_third = 1.0 / 3.0; 7.43 + static const float two_thirds = 2.0 / 3.0; 7.44 + static const float hcross[2][6] = { 7.45 + {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} }; 7.46 + static const float vcross[2][6] = { 7.47 + {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} }; 7.48 + static const float hsix[2][6] = { 7.49 + {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} }; 7.50 + 7.51 + Image img; 7.52 + if(!img.load(fname)) { 7.53 + return false; 7.54 + } 7.55 + 7.56 + int xsz = img.get_width(); 7.57 + int ysz = img.get_height(); 7.58 + 7.59 + if(xsz / 4 == ysz / 3) { 7.60 + // horizontal cross, assume the vertical bit is center-left 7.61 + return load_multi(img, hcross[0], hcross[1], xsz / 4); 7.62 + } 7.63 + if(xsz / 3 == ysz / 4) { 7.64 + // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) 7.65 + return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); 7.66 + } 7.67 + if(xsz / 3 == ysz / 2) { 7.68 + // horizontal sixpack 7.69 + return load_multi(img, hsix[0], hsix[1], ysz / 2); 7.70 + } 7.71 + 7.72 + error_log("failed to load %s: unknown cubemap configuration\n", fname); 7.73 + return false; 7.74 } 7.75 7.76 bool TextureCube::save(const char *fname) const 7.77 @@ -270,6 +314,27 @@ 7.78 return false; // TODO 7.79 } 7.80 7.81 +bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 7.82 + unsigned int rotmask) 7.83 +{ 7.84 + for(int i=0; i<6; i++) { 7.85 + Image face; 7.86 + 7.87 + int xoffs = xoffsets[i] * img.get_width(); 7.88 + int yoffs = yoffsets[i] * img.get_height(); 7.89 + 7.90 + if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) { 7.91 + return false; 7.92 + } 7.93 + 7.94 + if(rotmask & (1 << i)) { 7.95 + face.rotate_180(); 7.96 + } 7.97 + set_image(face, i); 7.98 + } 7.99 + return true; 7.100 +} 7.101 + 7.102 static int glifmt_from_ifmt(unsigned int ifmt) 7.103 { 7.104 #ifdef GL_ES_VERSION_2_0
8.1 --- a/src/texture.h Sun Nov 17 03:22:40 2013 +0200 8.2 +++ b/src/texture.h Sun Nov 17 08:20:13 2013 +0200 8.3 @@ -51,6 +51,10 @@ 8.4 }; 8.5 8.6 class TextureCube : public Texture { 8.7 +private: 8.8 + bool load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, 8.9 + unsigned int rotmask = 0); 8.10 + 8.11 public: 8.12 TextureCube(); 8.13