cubemapper

diff src/app.cc @ 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
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  		}