qvolray

annotate src/volray.cc @ 30:40df2cdc6323

transfer function window
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Apr 2012 22:10:30 +0300
parents 93d889a3726a
children 437e1ba9cf39
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <assert.h>
nuclear@0 4
nuclear@0 5 #include <GL/glew.h>
nuclear@0 6 #ifndef __APPLE__
nuclear@0 7 #include <GL/glut.h>
nuclear@0 8 #else
nuclear@0 9 #include <GLUT/glut.h>
nuclear@0 10 #endif
nuclear@0 11
nuclear@0 12 #include <vmath/vmath.h>
nuclear@0 13 #include <imago2.h>
nuclear@0 14 #include "sdr.h"
nuclear@9 15 #include "volume.h"
nuclear@13 16 #include "ui.h"
nuclear@18 17 #include "demo.h"
nuclear@0 18
nuclear@3 19 #define XFER_MAP_SZ 512
nuclear@3 20
nuclear@11 21 static void render_volume();
nuclear@5 22
nuclear@11 23 /*
nuclear@0 24 void keyb(unsigned char key, int x, int y);
nuclear@4 25 void keyb_up(unsigned char key, int x, int y);
nuclear@0 26 void mouse(int bn, int state, int x, int y);
nuclear@0 27 void motion(int x, int y);
nuclear@11 28 */
nuclear@0 29
nuclear@11 30 static void create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale);
nuclear@11 31 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg);
nuclear@0 32 static int round_pow2(int x);
nuclear@3 33 static void create_transfer_map(float mean, float sdev);
nuclear@0 34
nuclear@9 35 static float cam_theta = 0, cam_phi = 0, cam_dist = 4.0;
nuclear@9 36 static float cam_x, cam_y, cam_z;
nuclear@0 37
nuclear@13 38 static Vector2 tex_scale;
nuclear@9 39 static unsigned int vol_sdr, slice_sdr, ray_tex;
nuclear@9 40 static int win_xsz, win_ysz;
nuclear@11 41 static bool raytex_needs_recalc = true;
nuclear@0 42
nuclear@9 43 static unsigned int xfer_tex;
nuclear@9 44 static float xfer_mean = 0.7, xfer_sdev = 0.1;
nuclear@11 45 static bool xfertex_needs_recalc = true;
nuclear@3 46
nuclear@19 47 static float cur_z = 0.5;
nuclear@23 48 static bool clip_z;
nuclear@7 49 static float ray_step = 0.01;
nuclear@4 50
nuclear@18 51 static Volume *volume;
nuclear@9 52
nuclear@9 53
nuclear@11 54 bool volray_init()
nuclear@0 55 {
nuclear@0 56 glewInit();
nuclear@0 57
nuclear@9 58 if(!(vol_sdr = create_program_load("sdr/volray.v.glsl", "sdr/volray.p.glsl"))) {
nuclear@11 59 return false;
nuclear@0 60 }
nuclear@5 61 set_uniform_int(vol_sdr, "volume", 0);
nuclear@5 62 set_uniform_int(vol_sdr, "ray_tex", 1);
nuclear@5 63 set_uniform_int(vol_sdr, "xfer_tex", 2);
nuclear@7 64 set_uniform_float(vol_sdr, "ray_step", ray_step);
nuclear@23 65 set_uniform_float(vol_sdr, "zclip", 0.0);
nuclear@5 66
nuclear@9 67 if(!(slice_sdr = create_program_load(0, "sdr/slice.p.glsl"))) {
nuclear@11 68 return false;
nuclear@5 69 }
nuclear@5 70 set_uniform_int(slice_sdr, "volume", 0);
nuclear@5 71 set_uniform_int(slice_sdr, "xfer_tex", 1);
nuclear@0 72
nuclear@18 73 init_demo();
nuclear@18 74
nuclear@11 75 return true;
nuclear@0 76 }
nuclear@0 77
nuclear@18 78 void volray_setvolume(Volume *vol)
nuclear@13 79 {
nuclear@13 80 volume = vol;
nuclear@13 81 }
nuclear@13 82
nuclear@18 83 Volume *volray_getvolume()
nuclear@18 84 {
nuclear@18 85 return volume;
nuclear@18 86 }
nuclear@18 87
nuclear@29 88 void volray_setvalue(VolRayOpt which, float val)
nuclear@21 89 {
nuclear@21 90 switch(which) {
nuclear@29 91 case VolRayOpt::ZCURSOR:
nuclear@21 92 cur_z = val;
nuclear@23 93 if(clip_z) {
nuclear@23 94 set_uniform_float(vol_sdr, "zclip", cur_z);
nuclear@23 95 }
nuclear@21 96 post_redisplay();
nuclear@21 97 break;
nuclear@21 98
nuclear@29 99 case VolRayOpt::ZCLIP:
nuclear@23 100 clip_z = val > 0.5;
nuclear@23 101 set_uniform_float(vol_sdr, "zclip", clip_z ? cur_z : 0.0);
nuclear@23 102 post_redisplay();
nuclear@23 103 break;
nuclear@22 104
nuclear@21 105 default:
nuclear@21 106 break;
nuclear@21 107 }
nuclear@21 108 }
nuclear@21 109
nuclear@29 110 float volray_getvalue(VolRayOpt which)
nuclear@21 111 {
nuclear@21 112 switch(which) {
nuclear@29 113 case VolRayOpt::ZCURSOR:
nuclear@21 114 return cur_z;
nuclear@21 115
nuclear@29 116 case VolRayOpt::ZCLIP:
nuclear@23 117 return clip_z > 0.5 ? 1.0 : 0.0;
nuclear@23 118 break;
nuclear@23 119
nuclear@21 120 default:
nuclear@21 121 break;
nuclear@21 122 }
nuclear@21 123 return 0.0;
nuclear@21 124 }
nuclear@21 125
nuclear@11 126 void volray_draw(void)
nuclear@0 127 {
nuclear@4 128 /* recalculate primary ray texture if needed */
nuclear@1 129 if(raytex_needs_recalc) {
nuclear@1 130 create_ray_texture(win_xsz, win_ysz, 50.0, &tex_scale);
nuclear@1 131 }
nuclear@4 132 /* recalculate transfer function texture if needed */
nuclear@3 133 if(xfertex_needs_recalc) {
nuclear@3 134 create_transfer_map(xfer_mean, xfer_sdev);
nuclear@3 135 }
nuclear@1 136
nuclear@18 137 draw_demo();
nuclear@18 138
nuclear@13 139 glClear(GL_COLOR_BUFFER_BIT);
nuclear@13 140
nuclear@13 141 if(volume) {
nuclear@13 142 render_volume();
nuclear@13 143 }
nuclear@4 144
nuclear@4 145 assert(glGetError() == GL_NO_ERROR);
nuclear@4 146 }
nuclear@4 147
nuclear@11 148 static void render_volume(void)
nuclear@4 149 {
nuclear@4 150 /* set the camera transformation */
nuclear@0 151 glMatrixMode(GL_MODELVIEW);
nuclear@4 152 glPushMatrix();
nuclear@0 153 glLoadIdentity();
nuclear@1 154 glRotatef(-90, 1, 0, 0);
nuclear@0 155 glTranslatef(cam_x, cam_y, -cam_z);
nuclear@0 156 glRotatef(cam_theta, 0, 1, 0);
nuclear@0 157 glRotatef(cam_phi, 1, 0, 0);
nuclear@0 158 glTranslatef(0, 0, -cam_dist);
nuclear@0 159
nuclear@4 160 /* setup the texture matrix to map the useful part of the ray texture to [0,1] */
nuclear@0 161 glMatrixMode(GL_TEXTURE);
nuclear@4 162 glPushMatrix();
nuclear@1 163 glLoadIdentity();
nuclear@0 164 glScalef(tex_scale.x, tex_scale.y, 1.0);
nuclear@0 165
nuclear@4 166 /* tex unit0: volume data 3D texture */
nuclear@0 167 glActiveTexture(GL_TEXTURE0);
nuclear@13 168 glBindTexture(GL_TEXTURE_3D, volume->get_texture());
nuclear@0 169 glEnable(GL_TEXTURE_3D);
nuclear@0 170
nuclear@4 171 /* tex unit1: primary rays in view space */
nuclear@0 172 glActiveTexture(GL_TEXTURE1);
nuclear@1 173 glBindTexture(GL_TEXTURE_2D, ray_tex);
nuclear@0 174 glEnable(GL_TEXTURE_2D);
nuclear@0 175
nuclear@4 176 /* tex unit2: transfer function (1d) */
nuclear@3 177 glActiveTexture(GL_TEXTURE2);
nuclear@3 178 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@3 179 glEnable(GL_TEXTURE_1D);
nuclear@3 180
nuclear@5 181 bind_program(vol_sdr);
nuclear@0 182 glBegin(GL_QUADS);
nuclear@0 183 glColor3f(1, 1, 1);
nuclear@1 184 glTexCoord2f(0, 1); glVertex2f(-1, -1);
nuclear@1 185 glTexCoord2f(1, 1); glVertex2f(1, -1);
nuclear@1 186 glTexCoord2f(1, 0); glVertex2f(1, 1);
nuclear@1 187 glTexCoord2f(0, 0); glVertex2f(-1, 1);
nuclear@0 188 glEnd();
nuclear@0 189 bind_program(0);
nuclear@0 190
nuclear@3 191 glActiveTexture(GL_TEXTURE2);
nuclear@3 192 glDisable(GL_TEXTURE_1D);
nuclear@1 193 glActiveTexture(GL_TEXTURE1);
nuclear@0 194 glDisable(GL_TEXTURE_2D);
nuclear@0 195 glActiveTexture(GL_TEXTURE0);
nuclear@0 196 glDisable(GL_TEXTURE_3D);
nuclear@0 197
nuclear@0 198 glMatrixMode(GL_TEXTURE);
nuclear@4 199 glPopMatrix();
nuclear@4 200 glMatrixMode(GL_MODELVIEW);
nuclear@4 201 glPopMatrix();
nuclear@4 202 }
nuclear@0 203
nuclear@28 204 void volray_draw_slice(void)
nuclear@5 205 {
nuclear@5 206 glActiveTexture(GL_TEXTURE0);
nuclear@13 207 glBindTexture(GL_TEXTURE_3D, volume->get_texture());
nuclear@5 208 glEnable(GL_TEXTURE_3D);
nuclear@5 209
nuclear@5 210 glActiveTexture(GL_TEXTURE1);
nuclear@5 211 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@5 212 glEnable(GL_TEXTURE_1D);
nuclear@5 213
nuclear@5 214 bind_program(slice_sdr);
nuclear@5 215
nuclear@5 216 glBegin(GL_QUADS);
nuclear@5 217 glColor3f(1, 1, 1);
nuclear@5 218 glTexCoord3f(0, 1, cur_z); glVertex2f(-1, -1);
nuclear@5 219 glTexCoord3f(1, 1, cur_z); glVertex2f(1, -1);
nuclear@5 220 glTexCoord3f(1, 0, cur_z); glVertex2f(1, 1);
nuclear@5 221 glTexCoord3f(0, 0, cur_z); glVertex2f(-1, 1);
nuclear@5 222 glEnd();
nuclear@5 223
nuclear@5 224 bind_program(0);
nuclear@5 225
nuclear@5 226 glActiveTexture(GL_TEXTURE1);
nuclear@5 227 glDisable(GL_TEXTURE_1D);
nuclear@5 228 glActiveTexture(GL_TEXTURE0);
nuclear@5 229 glDisable(GL_TEXTURE_3D);
nuclear@5 230 }
nuclear@5 231
nuclear@29 232 void volray_draw_xfer(void)
nuclear@4 233 {
nuclear@4 234 glMatrixMode(GL_MODELVIEW);
nuclear@4 235 glPushMatrix();
nuclear@30 236 glTranslatef(-1, -1, 0);
nuclear@30 237 glScalef(2, 2, 1);
nuclear@4 238
nuclear@4 239 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@4 240 glEnable(GL_TEXTURE_1D);
nuclear@4 241
nuclear@4 242 glBegin(GL_QUADS);
nuclear@4 243 glColor3f(1, 1, 1);
nuclear@4 244 glTexCoord1f(1);
nuclear@4 245 glVertex2f(1, 0);
nuclear@4 246 glVertex2f(1, 1);
nuclear@4 247 glTexCoord1f(0);
nuclear@4 248 glVertex2f(0, 1);
nuclear@4 249 glVertex2f(0, 0);
nuclear@4 250 glEnd();
nuclear@4 251
nuclear@4 252 glDisable(GL_TEXTURE_1D);
nuclear@4 253
nuclear@4 254 glLineWidth(2.0);
nuclear@4 255 glBegin(GL_LINE_LOOP);
nuclear@13 256 /*if(uimode == UIMODE_XFER) {
nuclear@5 257 glColor3f(1, 0, 0);
nuclear@13 258 } else {*/
nuclear@5 259 glColor3f(0, 0, 1);
nuclear@13 260 //}
nuclear@4 261 glVertex2f(0, 0);
nuclear@4 262 glVertex2f(1, 0);
nuclear@4 263 glVertex2f(1, 1);
nuclear@4 264 glVertex2f(0, 1);
nuclear@4 265 glEnd();
nuclear@4 266
nuclear@4 267 glPopMatrix();
nuclear@0 268 }
nuclear@0 269
nuclear@11 270 void volray_resize(int x, int y)
nuclear@0 271 {
nuclear@0 272 glViewport(0, 0, x, y);
nuclear@0 273
nuclear@0 274 if(x != win_xsz || y != win_ysz) {
nuclear@11 275 raytex_needs_recalc = true;
nuclear@0 276 win_xsz = x;
nuclear@0 277 win_ysz = y;
nuclear@0 278 }
nuclear@0 279 }
nuclear@0 280
nuclear@11 281 #if 0
nuclear@0 282 void keyb(unsigned char key, int x, int y)
nuclear@0 283 {
nuclear@0 284 switch(key) {
nuclear@0 285 case 27:
nuclear@0 286 exit(0);
nuclear@4 287
nuclear@4 288 case 'x':
nuclear@5 289 uimode = UIMODE_XFER;
nuclear@13 290 post_redisplay();
nuclear@4 291 break;
nuclear@5 292
nuclear@5 293 case 'c':
nuclear@5 294 uimode = UIMODE_CURSOR;
nuclear@13 295 post_redisplay();
nuclear@5 296 break;
nuclear@5 297
nuclear@5 298 default:
nuclear@5 299 break;
nuclear@4 300 }
nuclear@4 301 }
nuclear@4 302
nuclear@4 303 void keyb_up(unsigned char key, int x, int y)
nuclear@4 304 {
nuclear@4 305 switch(key) {
nuclear@4 306 case 'x':
nuclear@5 307 if(uimode == UIMODE_XFER) {
nuclear@5 308 uimode = UIMODE_DEFAULT;
nuclear@13 309 post_redisplay();
nuclear@5 310 }
nuclear@5 311 break;
nuclear@5 312
nuclear@5 313 case 'c':
nuclear@5 314 if(uimode == UIMODE_CURSOR) {
nuclear@5 315 uimode = UIMODE_DEFAULT;
nuclear@13 316 post_redisplay();
nuclear@5 317 }
nuclear@5 318 break;
nuclear@5 319
nuclear@5 320 default:
nuclear@4 321 break;
nuclear@0 322 }
nuclear@0 323 }
nuclear@13 324 #endif
nuclear@0 325
nuclear@0 326 static int bnstate[32];
nuclear@0 327 static int prev_x, prev_y;
nuclear@0 328
nuclear@13 329 void volray_mouse(int bn, int state, int x, int y)
nuclear@0 330 {
nuclear@13 331 bnstate[bn] = state;
nuclear@0 332 prev_x = x;
nuclear@0 333 prev_y = y;
nuclear@0 334 }
nuclear@0 335
nuclear@13 336 void volray_motion(int x, int y)
nuclear@0 337 {
nuclear@0 338 int dx = x - prev_x;
nuclear@0 339 int dy = y - prev_y;
nuclear@0 340 prev_x = x;
nuclear@0 341 prev_y = y;
nuclear@0 342
nuclear@13 343 /*switch(uimode) {
nuclear@5 344 case UIMODE_XFER:
nuclear@4 345 if(dx || dy) {
nuclear@4 346 xfer_mean += dx / (float)win_xsz;
nuclear@4 347 xfer_sdev += 0.5 * dy / (float)win_ysz;
nuclear@0 348
nuclear@4 349 xfer_mean = xfer_mean < 0.0 ? 0.0 : (xfer_mean > 1.0 ? 1.0 : xfer_mean);
nuclear@4 350 xfer_sdev = xfer_sdev < 0.0 ? 0.0 : (xfer_sdev > 1.0 ? 1.0 : xfer_sdev);
nuclear@0 351
nuclear@11 352 xfertex_needs_recalc = true;
nuclear@13 353 post_redisplay();
nuclear@4 354 }
nuclear@5 355 break;
nuclear@0 356
nuclear@5 357 case UIMODE_CURSOR:
nuclear@5 358 cur_z += 0.5 * dy / (float)win_ysz;
nuclear@5 359
nuclear@5 360 if(cur_z < 0.0)
nuclear@5 361 cur_z = 0.0;
nuclear@5 362 if(cur_z > 1.0)
nuclear@5 363 cur_z = 1.0;
nuclear@7 364
nuclear@7 365 set_uniform_float(vol_sdr, "zclip", cur_z);
nuclear@13 366 post_redisplay();
nuclear@5 367 break;
nuclear@5 368
nuclear@13 369 default:*/
nuclear@5 370 /* view control */
nuclear@4 371 if(bnstate[0]) {
nuclear@4 372 cam_theta += dx * 0.5;
nuclear@4 373 cam_phi += dy * 0.5;
nuclear@0 374
nuclear@4 375 if(cam_phi <= -90) cam_phi = -89;
nuclear@4 376 if(cam_phi >= 90) cam_phi = 89;
nuclear@13 377 post_redisplay();
nuclear@4 378 }
nuclear@4 379
nuclear@4 380 if(bnstate[1]) {
nuclear@4 381 cam_x += dx * 0.025;
nuclear@4 382 cam_y += dy * 0.025;
nuclear@13 383 post_redisplay();
nuclear@4 384 }
nuclear@4 385
nuclear@4 386 if(bnstate[2]) {
nuclear@4 387 cam_dist += dy * 0.025;
nuclear@4 388 if(cam_dist < 0.0) cam_dist = 0.0;
nuclear@13 389 post_redisplay();
nuclear@4 390 }
nuclear@13 391 //}
nuclear@0 392 }
nuclear@0 393
nuclear@0 394 int parse_args(int argc, char **argv)
nuclear@0 395 {
nuclear@0 396 int i;
nuclear@3 397 char *endp;
nuclear@0 398
nuclear@0 399 for(i=1; i<argc; i++) {
nuclear@2 400 if(argv[i][0] == '-' && argv[i][2] == 0) {
nuclear@2 401 switch(argv[i][1]) {
nuclear@3 402 case 'm':
nuclear@3 403 xfer_mean = strtod(argv[++i], &endp);
nuclear@3 404 if(endp == argv[i]) {
nuclear@3 405 fprintf(stderr, "-m must be followed by the transfer function mean\n");
nuclear@3 406 return -1;
nuclear@3 407 }
nuclear@2 408 break;
nuclear@3 409
nuclear@4 410 case 'd':
nuclear@3 411 xfer_sdev = strtod(argv[++i], &endp);
nuclear@3 412 if(endp == argv[i]) {
nuclear@4 413 fprintf(stderr, "-d must be followed by the transfer function std.deviation\n");
nuclear@3 414 return -1;
nuclear@3 415 }
nuclear@3 416 break;
nuclear@3 417
nuclear@3 418 default:
nuclear@3 419 fprintf(stderr, "unrecognized option: %s\n", argv[i]);
nuclear@3 420 return -1;
nuclear@2 421 }
nuclear@2 422 } else {
nuclear@29 423 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
nuclear@0 424 }
nuclear@0 425 }
nuclear@0 426
nuclear@0 427 return 0;
nuclear@0 428 }
nuclear@0 429
nuclear@0 430
nuclear@11 431 static void create_ray_texture(int xsz, int ysz, float vfov, Vector2 *tex_scale)
nuclear@0 432 {
nuclear@1 433 int cur_tex_xsz, cur_tex_ysz;
nuclear@0 434 int tex_xsz = round_pow2(xsz);
nuclear@0 435 int tex_ysz = round_pow2(ysz);
nuclear@0 436 float *teximg, *dir;
nuclear@0 437
nuclear@11 438 teximg = new float[3 * xsz * ysz];
nuclear@0 439 dir = teximg;
nuclear@0 440
nuclear@11 441 for(int i=0; i<ysz; i++) {
nuclear@11 442 for(int j=0; j<xsz; j++) {
nuclear@11 443 Vector3 rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov);
nuclear@1 444 *dir++ = rdir.x;
nuclear@1 445 *dir++ = rdir.y;
nuclear@1 446 *dir++ = rdir.z;
nuclear@0 447 }
nuclear@0 448 }
nuclear@0 449
nuclear@1 450 if(!ray_tex) {
nuclear@1 451 glGenTextures(1, &ray_tex);
nuclear@1 452 }
nuclear@1 453
nuclear@1 454 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cur_tex_xsz);
nuclear@1 455 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cur_tex_ysz);
nuclear@1 456
nuclear@1 457 if(tex_xsz > cur_tex_xsz || tex_ysz > cur_tex_ysz) {
nuclear@1 458 glBindTexture(GL_TEXTURE_2D, ray_tex);
nuclear@1 459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
nuclear@1 460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
nuclear@1 461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
nuclear@1 462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
nuclear@1 463 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, 0);
nuclear@1 464 }
nuclear@1 465
nuclear@1 466 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, xsz, ysz, GL_RGB, GL_FLOAT, teximg);
nuclear@11 467 delete [] teximg;
nuclear@0 468
nuclear@0 469 if(tex_scale) {
nuclear@0 470 tex_scale->x = (float)xsz / (float)tex_xsz;
nuclear@0 471 tex_scale->y = (float)ysz / (float)tex_ysz;
nuclear@0 472 }
nuclear@11 473 raytex_needs_recalc = false;
nuclear@0 474 }
nuclear@0 475
nuclear@11 476 static Vector3 get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg)
nuclear@0 477 {
nuclear@0 478 float vfov = M_PI * vfov_deg / 180.0;
nuclear@0 479 float aspect = (float)w / (float)h;
nuclear@0 480
nuclear@0 481 float ysz = 2.0;
nuclear@0 482 float xsz = aspect * ysz;
nuclear@0 483
nuclear@0 484 float px = ((float)x / (float)w) * xsz - xsz / 2.0;
nuclear@0 485 float py = 1.0 - ((float)y / (float)h) * ysz;
nuclear@0 486 float pz = 1.0 / tan(0.5 * vfov);
nuclear@0 487
nuclear@0 488 float mag = sqrt(px * px + py * py + pz * pz);
nuclear@11 489 return Vector3(px / mag, py / mag, pz / mag);
nuclear@0 490 }
nuclear@0 491
nuclear@0 492 static int round_pow2(int x)
nuclear@0 493 {
nuclear@0 494 x--;
nuclear@0 495 x = (x >> 1) | x;
nuclear@0 496 x = (x >> 2) | x;
nuclear@0 497 x = (x >> 4) | x;
nuclear@0 498 x = (x >> 8) | x;
nuclear@0 499 x = (x >> 16) | x;
nuclear@0 500 return x + 1;
nuclear@0 501 }
nuclear@0 502
nuclear@3 503 static void create_transfer_map(float mean, float sdev)
nuclear@3 504 {
nuclear@3 505 static float map[XFER_MAP_SZ];
nuclear@3 506
nuclear@3 507 if(!xfer_tex) {
nuclear@3 508 glGenTextures(1, &xfer_tex);
nuclear@3 509 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@3 510 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@3 511 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@3 512 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
nuclear@3 513 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
nuclear@3 514 glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE32F_ARB, XFER_MAP_SZ, 0, GL_LUMINANCE, GL_FLOAT, 0);
nuclear@3 515 }
nuclear@3 516
nuclear@11 517 for(int i=0; i<XFER_MAP_SZ; i++) {
nuclear@4 518 float x = (float)i / (float)(XFER_MAP_SZ - 1);
nuclear@4 519 map[i] = gaussian(x, mean, sdev) - 1.0;
nuclear@3 520 }
nuclear@3 521
nuclear@4 522 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_LUMINANCE, GL_FLOAT, map);
nuclear@11 523 xfertex_needs_recalc = false;
nuclear@3 524 }