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