cubemapper

changeset 2:e308561f9889

correct cubemap export and visualization
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 28 Jul 2017 13:24:34 +0300
parents d7a29cb7ac8d
children f5cc465eb735
files src/app.cc src/app.h src/main.cc src/texture.cc
diffstat 4 files changed, 131 insertions(+), 68 deletions(-) [+]
line diff
     1.1 --- a/src/app.cc	Fri Jul 28 07:44:35 2017 +0300
     1.2 +++ b/src/app.cc	Fri Jul 28 13:24:34 2017 +0300
     1.3 @@ -10,10 +10,8 @@
     1.4  #include "mesh.h"
     1.5  #include "meshgen.h"
     1.6  
     1.7 -static void draw_scene();	// both near and infinite parts
     1.8 -static void draw_scene_near();	// near scene: regular objects affected by parallax shift and translation
     1.9 -// infinity scene: objects conceptually at infinity, not affected by parallax shift and translation
    1.10 -static void draw_scene_inf();
    1.11 +static void draw_equilateral();
    1.12 +static void draw_cubemap();
    1.13  static bool parse_args(int argc, char **argv);
    1.14  
    1.15  static void flip_image(float *pixels, int xsz, int ysz);
    1.16 @@ -25,6 +23,11 @@
    1.17  static Mesh *pano_mesh;
    1.18  
    1.19  static int win_width, win_height;
    1.20 +static int show_cubemap;
    1.21 +
    1.22 +static unsigned int fbo;
    1.23 +static unsigned int cube_tex;
    1.24 +static int cube_size;
    1.25  
    1.26  
    1.27  bool app_init(int argc, char **argv)
    1.28 @@ -41,15 +44,7 @@
    1.29  		return false;
    1.30  	}
    1.31  
    1.32 -	glEnable(GL_CULL_FACE);
    1.33 -
    1.34 -	if(GLEW_ARB_framebuffer_sRGB) {
    1.35 -		glGetError();	// discard previous errors
    1.36 -		glEnable(GL_FRAMEBUFFER_SRGB);
    1.37 -		if(glGetError() != GL_NO_ERROR) {
    1.38 -			fprintf(stderr, "failed to enable sRGB framebuffer\n");
    1.39 -		}
    1.40 -	}
    1.41 +	glEnable(GL_MULTISAMPLE);
    1.42  
    1.43  	Mesh::use_custom_sdr_attr = false;
    1.44  	pano_mesh = new Mesh;
    1.45 @@ -67,6 +62,34 @@
    1.46  		return false;
    1.47  	}
    1.48  	printf("loaded image: %dx%d\n", pano_tex->get_width(), pano_tex->get_height());
    1.49 +
    1.50 +	// create cubemap
    1.51 +	cube_size = pano_tex->get_height();
    1.52 +	glGenTextures(1, &cube_tex);
    1.53 +	glBindTexture(GL_TEXTURE_CUBE_MAP, cube_tex);
    1.54 +	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    1.55 +	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    1.56 +	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    1.57 +	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    1.58 +	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    1.59 +
    1.60 +	for(int i=0; i<6; i++) {
    1.61 +		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, cube_size, cube_size,
    1.62 +				0, GL_RGB, GL_FLOAT, 0);
    1.63 +	}
    1.64 +
    1.65 +
    1.66 +	// create fbo
    1.67 +	glGenFramebuffers(1, &fbo);
    1.68 +
    1.69 +	// tex-gen for cubemap visualization
    1.70 +	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    1.71 +	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    1.72 +	glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    1.73 +	float planes[][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}};
    1.74 +	glTexGenfv(GL_S, GL_OBJECT_PLANE, planes[0]);
    1.75 +	glTexGenfv(GL_T, GL_OBJECT_PLANE, planes[1]);
    1.76 +	glTexGenfv(GL_R, GL_OBJECT_PLANE, planes[2]);
    1.77  	return true;
    1.78  }
    1.79  
    1.80 @@ -87,7 +110,22 @@
    1.81  	glMatrixMode(GL_MODELVIEW);
    1.82  	glLoadMatrixf(view_matrix[0]);
    1.83  
    1.84 -	draw_scene();
    1.85 +	if(show_cubemap) {
    1.86 +		draw_cubemap();
    1.87 +
    1.88 +		glColor3f(0, 0, 0);
    1.89 +		app_print_text(10, 10, "cubemap");
    1.90 +		glColor3f(0, 0.8, 1);
    1.91 +		app_print_text(8, 13, "cubemap");
    1.92 +	} else {
    1.93 +		draw_equilateral();
    1.94 +
    1.95 +		glColor3f(0, 0, 0);
    1.96 +		app_print_text(10, 10, "equilateral");
    1.97 +		glColor3f(1, 0.8, 0);
    1.98 +		app_print_text(8, 13, "equilateral");
    1.99 +	}
   1.100 +	glColor3f(1, 1, 1);
   1.101  
   1.102  	app_swap_buffers();
   1.103  	assert(glGetError() == GL_NO_ERROR);
   1.104 @@ -95,62 +133,72 @@
   1.105  
   1.106  void render_cubemap()
   1.107  {
   1.108 -	int fbsize = win_width < win_height ? win_width : win_height;
   1.109 -	float *pixels = new float[fbsize * fbsize * 3];
   1.110 +	printf("rendering cubemap %dx%d\n", cube_size, cube_size);
   1.111  
   1.112 -	glViewport(0, 0, fbsize, fbsize);
   1.113 +	float *pixels = new float[cube_size * cube_size * 3];
   1.114 +
   1.115 +	glViewport(0, 0, cube_size, cube_size);
   1.116  
   1.117  	Mat4 viewmat[6];
   1.118  	viewmat[0].rotation_y(deg_to_rad(90));	// +X
   1.119 -	viewmat[1].rotation_x(deg_to_rad(-90));	// +Y
   1.120 -	viewmat[2].rotation_y(deg_to_rad(180));	// +Z
   1.121 -	viewmat[3].rotation_y(deg_to_rad(-90));	// -X
   1.122 -	viewmat[4].rotation_x(deg_to_rad(90));	// -Y
   1.123 +	viewmat[1].rotation_y(deg_to_rad(-90));	// -X
   1.124 +	viewmat[2].rotation_x(deg_to_rad(90));	// +Y
   1.125 +	viewmat[2].rotate_y(deg_to_rad(180));
   1.126 +	viewmat[3].rotation_x(deg_to_rad(-90));	// -Y
   1.127 +	viewmat[3].rotate_y(deg_to_rad(180));
   1.128 +	viewmat[4].rotation_y(deg_to_rad(180));	// +Z
   1.129  
   1.130 +	// this must coincide with the order of GL_TEXTURE_CUBE_MAP_* values
   1.131  	static const char *fname[] = {
   1.132  		"cubemap_px.jpg",
   1.133 +		"cubemap_nx.jpg",
   1.134  		"cubemap_py.jpg",
   1.135 +		"cubemap_ny.jpg",
   1.136  		"cubemap_pz.jpg",
   1.137 -		"cubemap_nx.jpg",
   1.138 -		"cubemap_ny.jpg",
   1.139  		"cubemap_nz.jpg"
   1.140  	};
   1.141  
   1.142  	glMatrixMode(GL_PROJECTION);
   1.143 +	glPushMatrix();
   1.144  	glLoadIdentity();
   1.145 -	gluPerspective(45, 1.0, 0.5, 500.0);
   1.146 +	gluPerspective(90, 1.0, 0.5, 500.0);
   1.147 +	glScalef(-1, -1, 1);
   1.148 +
   1.149 +	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
   1.150  
   1.151  	for(int i=0; i<6; i++) {
   1.152 +		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
   1.153 +				GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cube_tex, 0);
   1.154 +
   1.155  		glClear(GL_COLOR_BUFFER_BIT);
   1.156  
   1.157  		glMatrixMode(GL_MODELVIEW);
   1.158  		glLoadMatrixf(viewmat[i][0]);
   1.159  
   1.160 -		draw_scene();
   1.161 +		draw_equilateral();
   1.162  
   1.163 -		glReadPixels(0, 0, fbsize, fbsize, GL_RGB, GL_FLOAT, pixels);
   1.164 -		flip_image(pixels, fbsize, fbsize);
   1.165 +		//glReadPixels(0, 0, cube_size, cube_size, GL_RGB, GL_FLOAT, pixels);
   1.166 +		glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, GL_FLOAT, pixels);
   1.167 +		//flip_image(pixels, cube_size, cube_size);
   1.168  
   1.169 -		if(img_save_pixels(fname[i], pixels, fbsize, fbsize, IMG_FMT_RGBF) == -1) {
   1.170 -			fprintf(stderr, "failed to save %dx%d image: %s\n", fbsize, fbsize, fname[i]);
   1.171 -			break;
   1.172 +		if(img_save_pixels(fname[i], pixels, cube_size, cube_size, IMG_FMT_RGBF) == -1) {
   1.173 +			fprintf(stderr, "failed to save %dx%d image: %s\n", cube_size, cube_size, fname[i]);
   1.174  		}
   1.175  	}
   1.176  
   1.177 +	glBindFramebuffer(GL_FRAMEBUFFER, 0);
   1.178  	glViewport(0, 0, win_width, win_height);
   1.179  
   1.180 +	glMatrixMode(GL_PROJECTION);
   1.181 +	glPopMatrix();
   1.182 +
   1.183  	delete [] pixels;
   1.184 +
   1.185 +	glBindTexture(GL_TEXTURE_CUBE_MAP, cube_tex);
   1.186 +	glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
   1.187  }
   1.188  
   1.189 -// both near and infinite parts (see below)
   1.190 -static void draw_scene()
   1.191 -{
   1.192 -	draw_scene_inf();
   1.193 -	draw_scene_near();
   1.194 -}
   1.195 -
   1.196 -// infinity scene: objects conceptually at infinity, not affected by parallax shift and translation
   1.197 -static void draw_scene_inf()
   1.198 +static void draw_equilateral()
   1.199  {
   1.200  	pano_tex->bind();
   1.201  	glEnable(GL_TEXTURE_2D);
   1.202 @@ -158,9 +206,19 @@
   1.203  	glDisable(GL_TEXTURE_2D);
   1.204  }
   1.205  
   1.206 -// near scene: regular objects affected by parallax shift and translation
   1.207 -static void draw_scene_near()
   1.208 +static void draw_cubemap()
   1.209  {
   1.210 +	glPushAttrib(GL_ENABLE_BIT);
   1.211 +
   1.212 +	glBindTexture(GL_TEXTURE_CUBE_MAP, cube_tex);
   1.213 +	glEnable(GL_TEXTURE_CUBE_MAP);
   1.214 +	glEnable(GL_TEXTURE_GEN_S);
   1.215 +	glEnable(GL_TEXTURE_GEN_T);
   1.216 +	glEnable(GL_TEXTURE_GEN_R);
   1.217 +
   1.218 +	pano_mesh->draw();
   1.219 +
   1.220 +	glPopAttrib();
   1.221  }
   1.222  
   1.223  void app_reshape(int x, int y)
   1.224 @@ -177,8 +235,6 @@
   1.225  
   1.226  void app_keyboard(int key, bool press)
   1.227  {
   1.228 -	int cubemap_size;
   1.229 -
   1.230  	if(press) {
   1.231  		switch(key) {
   1.232  		case 27:
   1.233 @@ -186,12 +242,11 @@
   1.234  			break;
   1.235  
   1.236  		case ' ':
   1.237 -			cubemap_size = pano_tex->get_width() / 4;
   1.238 -			app_resize(cubemap_size, cubemap_size);
   1.239 +			show_cubemap = !show_cubemap;
   1.240 +			app_redisplay();
   1.241  			break;
   1.242  
   1.243 -		case 's':
   1.244 -			printf("rendering cubemap\n");
   1.245 +		case 'c':
   1.246  			render_cubemap();
   1.247  			break;
   1.248  		}
     2.1 --- a/src/app.h	Fri Jul 28 07:44:35 2017 +0300
     2.2 +++ b/src/app.h	Fri Jul 28 13:24:34 2017 +0300
     2.3 @@ -16,5 +16,6 @@
     2.4  void app_redisplay();
     2.5  void app_swap_buffers();
     2.6  void app_resize(int x, int y);
     2.7 +void app_print_text(int x, int y, const char *str);
     2.8  
     2.9  #endif	// APP_H_
     3.1 --- a/src/main.cc	Fri Jul 28 07:44:35 2017 +0300
     3.2 +++ b/src/main.cc	Fri Jul 28 13:24:34 2017 +0300
     3.3 @@ -12,11 +12,13 @@
     3.4  static void mouse(int bn, int st, int x, int y);
     3.5  static void motion(int x, int y);
     3.6  
     3.7 +static int win_width, win_height;
     3.8 +
     3.9  int main(int argc, char **argv)
    3.10  {
    3.11  	glutInitWindowSize(1024, 768);
    3.12  	glutInit(&argc, argv);
    3.13 -	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    3.14 +	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
    3.15  	glutCreateWindow("cubemapper");
    3.16  
    3.17  	glutDisplayFunc(display);
    3.18 @@ -54,6 +56,29 @@
    3.19  	glutReshapeWindow(x, y);
    3.20  }
    3.21  
    3.22 +void app_print_text(int x, int y, const char *str)
    3.23 +{
    3.24 +	glMatrixMode(GL_PROJECTION);
    3.25 +	glPushMatrix();
    3.26 +	glLoadIdentity();
    3.27 +	glOrtho(0, win_width, 0, win_height, -1, 1);
    3.28 +
    3.29 +	glMatrixMode(GL_MODELVIEW);
    3.30 +	glPushMatrix();
    3.31 +	glLoadIdentity();
    3.32 +
    3.33 +	glRasterPos2i(x, y);
    3.34 +
    3.35 +	while(*str) {
    3.36 +		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *str++);
    3.37 +	}
    3.38 +
    3.39 +	glMatrixMode(GL_PROJECTION);
    3.40 +	glPopMatrix();
    3.41 +	glMatrixMode(GL_MODELVIEW);
    3.42 +	glPopMatrix();
    3.43 +}
    3.44 +
    3.45  static void display()
    3.46  {
    3.47  	app_draw();
    3.48 @@ -61,6 +86,8 @@
    3.49  
    3.50  static void reshape(int x, int y)
    3.51  {
    3.52 +	win_width = x;
    3.53 +	win_height = y;
    3.54  	app_reshape(x, y);
    3.55  }
    3.56  
     4.1 --- a/src/texture.cc	Fri Jul 28 07:44:35 2017 +0300
     4.2 +++ b/src/texture.cc	Fri Jul 28 13:24:34 2017 +0300
     4.3 @@ -51,26 +51,6 @@
     4.4  	unsigned int pixfmt = img_glfmt(&img);
     4.5  	unsigned int pixtype = img_gltype(&img);
     4.6  
     4.7 -	// if we have the sRGB extension, change the internal formats to sRGB
     4.8 -	if(GLEW_EXT_texture_sRGB) {
     4.9 -		switch(intfmt) {
    4.10 -		case 3:
    4.11 -		case GL_RGB:
    4.12 -			intfmt = GL_SRGB_EXT;
    4.13 -			break;
    4.14 -		case 4:
    4.15 -		case GL_RGBA:
    4.16 -			intfmt = GL_SRGB_ALPHA;
    4.17 -			break;
    4.18 -		case 1:
    4.19 -		case GL_LUMINANCE:
    4.20 -			intfmt = GL_SLUMINANCE;
    4.21 -			break;
    4.22 -		default:
    4.23 -			break;
    4.24 -		}
    4.25 -	}
    4.26 -
    4.27  	width = img.width;
    4.28  	height = img.height;
    4.29  	tex_width = next_pow2(width);