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);