00001 #ifndef OPENTISSUE_GPU_TEXTURE_TEXTURE_TEXTURE3D_H
00002 #define OPENTISSUE_GPU_TEXTURE_TEXTURE_TEXTURE3D_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/utility/gl/gl_util.h>
00013 #include <OpenTissue/core/math/math_power2.h>
00014 #include <OpenTissue/gpu/texture/texture_types.h>
00015
00016 #include <boost/shared_ptr.hpp>
00017
00018 #include <iostream>
00019 #include <cassert>
00020
00021 namespace OpenTissue
00022 {
00023 namespace texture
00024 {
00025
00030 class Texture3D
00031 {
00032 protected:
00033
00034
00035 GLuint m_texture_ID;
00036 int m_internal_format;
00037 bool m_owned;
00038 int m_image_skip_i;
00039 int m_image_skip_j;
00040 int m_image_skip_k;
00041 int m_image_size_i;
00042 int m_image_size_j;
00043 int m_image_size_k;
00044 int m_texture_size_i;
00045 int m_texture_size_j;
00046 int m_texture_size_k;
00047 unsigned int m_format;
00048 unsigned int m_type;
00049 bool m_cubic;
00050 unsigned int m_texture_target;
00051 float m_unpack_scale;
00052
00053 public:
00054
00055 unsigned int get_texture_ID() const { return m_texture_ID; }
00056 unsigned int get_texture_target() const { return m_texture_target; }
00057 int width() const { return m_texture_size_i; }
00058 int height() const { return m_texture_size_j; }
00059 int depth() const { return m_texture_size_k; }
00060 int get_internal_format() const { return m_internal_format; }
00061 bool cubic() const { return m_cubic; }
00062 float unpack_scale() const { return m_unpack_scale; }
00063
00064 protected:
00065
00066 void create(unsigned int texture_ID = 0)
00067 {
00068 m_texture_ID = texture_ID;
00069 m_owned=false;
00070 if (m_texture_ID==0)
00071 {
00072 glGenTextures(1, &m_texture_ID);
00073 m_owned = true;
00074 if(m_texture_ID == 0)
00075 {
00076 std::cerr<< "Texture3D::create(): Could not create texture ID";
00077 }
00078 }
00079 }
00080
00081 public:
00082
00112 int check_texture_size(
00113 int internal_format
00114 , int width
00115 , int height
00116 , int depth
00117 , int external_format
00118 , int external_type
00119 )
00120 {
00121 using std::ceil;
00122
00123
00124 GLint max_tex_size;
00125 GLint max_tex_size_ext;
00126 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max_tex_size);
00127 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &max_tex_size_ext);
00128 if(width>max_tex_size ||height>max_tex_size || depth>max_tex_size )
00129 return 0;
00130 if(width>max_tex_size_ext ||height>max_tex_size_ext || depth>max_tex_size_ext )
00131 return 0;
00132
00133
00134
00135
00136 unsigned int m_proxy_texture_target = GL_PROXY_TEXTURE_3D;
00137 glTexImage3D( m_proxy_texture_target, 0, internal_format, width, height, depth, 0, external_format, external_type, 0 );
00138 GLint tex_size[ 3 ] = { 0, 0, 0 };
00139 GLint channel_size[ 6 ] = { 0, 0, 0, 0, 0, 0};
00140 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_WIDTH , &( tex_size[ 0 ] ) );
00141 if(tex_size[0]==0)
00142 return 0;
00143 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_HEIGHT , &( tex_size[ 1 ] ) );
00144 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_DEPTH , &( tex_size[ 2 ] ) );
00145 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_RED_SIZE , &( channel_size[ 0 ] ) );
00146 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_GREEN_SIZE , &( channel_size[ 1 ] ) );
00147 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_BLUE_SIZE , &( channel_size[ 2 ] ) );
00148 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_ALPHA_SIZE , &( channel_size[ 3 ] ) );
00149 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_LUMINANCE_SIZE, &( channel_size[ 4 ] ) );
00150 glGetTexLevelParameteriv( m_proxy_texture_target, 0, GL_TEXTURE_INTENSITY_SIZE, &( channel_size[ 5 ] ) );
00151 int total_bits = channel_size[ 0 ] + channel_size[ 1 ] + channel_size[ 2 ] + channel_size[ 3 ] + channel_size[ 4 ] + channel_size[ 5 ];
00152 float bytes = static_cast< float >( ceil( total_bits / 8.0 ));
00153 int memory_size = static_cast<int>(tex_size[ 0 ] * tex_size[ 1 ] * tex_size[ 2 ] * bytes);
00154 return memory_size;
00155 }
00156
00157
00158 protected:
00159
00160 GLint m_tmp[10];
00161
00166 void setup_pixel_transfer()
00167 {
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 float bias = 0.0;
00184
00185
00186
00187 glPixelTransferf ( GL_RED_SCALE , m_unpack_scale );
00188 glPixelTransferf ( GL_GREEN_SCALE , m_unpack_scale );
00189 glPixelTransferf ( GL_BLUE_SCALE , m_unpack_scale );
00190 glPixelTransferf ( GL_RED_BIAS , bias );
00191 glPixelTransferf ( GL_GREEN_BIAS , bias );
00192 glPixelTransferf ( GL_BLUE_BIAS , bias );
00193
00194
00195
00196
00197 glGetIntegerv ( GL_UNPACK_ROW_LENGTH , &m_tmp[0] );
00198 glGetIntegerv ( GL_UNPACK_IMAGE_HEIGHT , &m_tmp[1] );
00199 glGetIntegerv ( GL_UNPACK_ALIGNMENT , &m_tmp[2] );
00200 glGetIntegerv ( GL_UNPACK_SKIP_PIXELS , &m_tmp[3] );
00201 glGetIntegerv ( GL_UNPACK_SKIP_ROWS , &m_tmp[4] );
00202 glGetIntegerv ( GL_UNPACK_SKIP_IMAGES , &m_tmp[5] );
00203
00204
00205
00206
00207
00208
00209
00210 glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 );
00211 glPixelStorei ( GL_UNPACK_ROW_LENGTH , m_image_size_i );
00212 glPixelStorei ( GL_UNPACK_IMAGE_HEIGHT , m_image_size_j );
00213 glPixelStorei ( GL_UNPACK_SKIP_PIXELS , m_image_skip_i );
00214 glPixelStorei ( GL_UNPACK_SKIP_ROWS , m_image_skip_j );
00215 glPixelStorei ( GL_UNPACK_SKIP_IMAGES , m_image_skip_k );
00216 }
00217
00218
00223 void clear_pixel_transfer()
00224 {
00225 glPixelStorei ( GL_UNPACK_ROW_LENGTH , m_tmp[0] );
00226 glPixelStorei ( GL_UNPACK_IMAGE_HEIGHT , m_tmp[1] );
00227 glPixelStorei ( GL_UNPACK_ALIGNMENT , m_tmp[2] );
00228 glPixelStorei ( GL_UNPACK_SKIP_PIXELS , m_tmp[3] );
00229 glPixelStorei ( GL_UNPACK_SKIP_ROWS , m_tmp[4] );
00230 glPixelStorei ( GL_UNPACK_SKIP_IMAGES , m_tmp[5] );
00231
00232
00233 glPixelTransferf ( GL_RED_SCALE , 1.0 );
00234 glPixelTransferf ( GL_GREEN_SCALE , 1.0 );
00235 glPixelTransferf ( GL_BLUE_SCALE , 1.0 );
00236 glPixelTransferf ( GL_RED_BIAS , 0 );
00237 glPixelTransferf ( GL_GREEN_BIAS , 0 );
00238 glPixelTransferf ( GL_BLUE_BIAS , 0 );
00239 }
00240
00241 public:
00242
00272 Texture3D(
00273 int internal_format
00274 , int image_width
00275 , int image_height
00276 , int image_depth
00277 , int format
00278 , int type
00279 , const void *pixels
00280 , bool cubic=false
00281 , float unpack_scale = 1.0
00282 )
00283 : m_internal_format(internal_format)
00284 , m_image_skip_i(0)
00285 , m_image_skip_j(0)
00286 , m_image_skip_k(0)
00287 , m_image_size_i( image_width )
00288 , m_image_size_j( image_height )
00289 , m_image_size_k( image_depth )
00290 , m_texture_size_i( math::lower_power2(m_image_size_i) )
00291 , m_texture_size_j( math::lower_power2(m_image_size_j) )
00292 , m_texture_size_k( math::lower_power2(m_image_size_k) )
00293 , m_format(format)
00294 , m_type(type)
00295 , m_cubic(cubic)
00296 , m_texture_target( GL_TEXTURE_3D )
00297 , m_unpack_scale(unpack_scale)
00298 {
00299
00300 assert( math::is_power2( m_texture_size_i ) || !"Texture3D(): Texture width was not a power of two" );
00301 assert( math::is_power2( m_texture_size_j ) || !"Texture3D(): Texture height was not a power of two" );
00302 assert( math::is_power2( m_texture_size_k ) || !"Texture3D(): Texture depth was not a power of two" );
00303 int memory_size = check_texture_size(internal_format,m_texture_size_i,m_texture_size_j,m_texture_size_k,format,type);
00304 assert(memory_size>0 || !"Texture3D(): insuficient memory could not load 3D texture");
00305 std::cout << "Texture3D(): memory = " << memory_size << " bytes" << std::endl;
00306
00307 create();
00308 glEnable(m_texture_target);
00309 glBindTexture(m_texture_target, m_texture_ID);
00310 setup_pixel_transfer();
00311
00312
00313 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00314 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00315 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00316 glTexParameteri( m_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00317 glTexParameteri( m_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00318
00319
00320 glTexImage3D(
00321 m_texture_target
00322 , 0
00323 , internal_format
00324 , m_texture_size_i
00325 , m_texture_size_j
00326 , m_texture_size_k
00327 , 0
00328 , format
00329 , type
00330 , pixels
00331 );
00332
00333 clear_pixel_transfer();
00334 }
00335
00364 Texture3D(
00365 int internal_format
00366 , int texture_size_i
00367 , int texture_size_j
00368 , int texture_size_k
00369 , int format
00370 , int type
00371 , bool cubic=false
00372 , float unpack_scale = 1.0
00373 )
00374 : m_internal_format(internal_format)
00375 , m_image_skip_i(0)
00376 , m_image_skip_j(0)
00377 , m_image_skip_k(0)
00378 , m_image_size_i( texture_size_i )
00379 , m_image_size_j( texture_size_j )
00380 , m_image_size_k( texture_size_k )
00381 , m_texture_size_i( math::lower_power2(texture_size_i) )
00382 , m_texture_size_j( math::lower_power2(texture_size_j) )
00383 , m_texture_size_k( math::lower_power2(texture_size_k) )
00384 , m_format(format)
00385 , m_type(type)
00386 , m_cubic(cubic)
00387 , m_texture_target( GL_TEXTURE_3D )
00388 , m_unpack_scale(unpack_scale)
00389 {
00390
00391 assert( math::is_power2( m_texture_size_i ) || !"Texture3D(): Texture width was not a power of two" );
00392 assert( math::is_power2( m_texture_size_j ) || !"Texture3D(): Texture height was not a power of two" );
00393 assert( math::is_power2( m_texture_size_k ) || !"Texture3D(): Texture depth was not a power of two" );
00394 int memory_size = check_texture_size(internal_format,m_texture_size_i,m_texture_size_j,m_texture_size_k,format,type);
00395 assert(memory_size>0 || !"Texture3D(): insuficient memory could not load 3D texture");
00396 std::cout << "Texture3D(): memory = " << memory_size << " bytes" << std::endl;
00397 create();
00398 glEnable(m_texture_target);
00399 glBindTexture(m_texture_target, m_texture_ID);
00400
00401 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00402 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00403 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00404 glTexParameteri( m_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00405 glTexParameteri( m_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00406
00407 glTexImage3D(
00408 m_texture_target
00409 , 0
00410 , internal_format
00411 , m_texture_size_i
00412 , m_texture_size_j
00413 , m_texture_size_k
00414 , 0
00415 , format
00416 , type
00417 , 0
00418 );
00419 }
00420
00421 ~Texture3D()
00422 {
00423 if (m_texture_ID!=0 && m_owned)
00424 glDeleteTextures(1, &m_texture_ID);
00425 }
00426
00427 public:
00428
00434 void bind() const
00435 {
00436 if( !glIsEnabled(m_texture_target) )
00437 glEnable(m_texture_target);
00438 glBindTexture(m_texture_target, m_texture_ID);
00439 }
00440
00441
00460 template <typename T>
00461 void load_sub_image_into_texture(
00462 int image_skip_i
00463 , int image_skip_j
00464 , int image_skip_k
00465 , int image_size_i
00466 , int image_size_j
00467 , int image_size_k
00468 , int texture_offset_i
00469 , int texture_offset_j
00470 , int texture_offset_k
00471 , int texture_fill_i
00472 , int texture_fill_j
00473 , int texture_fill_k
00474 , T const * pixels
00475 )
00476 {
00477 assert(image_skip_i>=0 || !"Texture3D::load_sub_image_into_texture(): skip i was negative");
00478 assert(image_skip_j>=0 || !"Texture3D::load_sub_image_into_texture(): skip j was negative");
00479 assert(image_skip_k>=0 || !"Texture3D::load_sub_image_into_texture(): skip k was negative");
00480
00481 assert(image_size_i>0 || !"Texture3D::load_sub_image_into_texture(): size i was non positive");
00482 assert(image_size_j>0 || !"Texture3D::load_sub_image_into_texture(): size j was non positive");
00483 assert(image_size_k>0 || !"Texture3D::load_sub_image_into_texture(): size k was non positive");
00484
00485 assert(image_skip_i < image_size_i || !"Texture3D::load_sub_image_into_texture(): skip i was larger than size");
00486 assert(image_skip_j < image_size_j || !"Texture3D::load_sub_image_into_texture(): skip j was larger than size");
00487 assert(image_skip_k < image_size_k || !"Texture3D::load_sub_image_into_texture(): skip k was larger than size");
00488
00489 assert(texture_offset_i>=0 || !"Texture3D::load_sub_image_into_texture(): offset i was negative");
00490 assert(texture_offset_j>=0 || !"Texture3D::load_sub_image_into_texture(): offset j was negative");
00491 assert(texture_offset_k>=0 || !"Texture3D::load_sub_image_into_texture(): offset k was negative");
00492
00493 assert(texture_offset_i < m_texture_size_i || !"Texture3D::load_sub_image_into_texture(): offset i was larger than texture size");
00494 assert(texture_offset_j < m_texture_size_j || !"Texture3D::load_sub_image_into_texture(): offset j was larger than texture size");
00495 assert(texture_offset_k < m_texture_size_k || !"Texture3D::load_sub_image_into_texture(): offset k was larger than texture size");
00496
00497 assert((texture_offset_i+texture_fill_i) <= m_texture_size_i || !"Texture3D::load_sub_image_into_texture(): texture fill exceeds texture size");
00498 assert((texture_offset_j+texture_fill_j) <= m_texture_size_j || !"Texture3D::load_sub_image_into_texture(): texture fill exceeds texture size");
00499 assert((texture_offset_k+texture_fill_k) <= m_texture_size_k || !"Texture3D::load_sub_image_into_texture(): texture fill exceeds texture size");
00500
00501 assert(texture_fill_i <= (image_size_i - image_skip_i) || !"Texture3D::load_sub_image_into_texture(): texture fill i was larger than sub image region");
00502 assert(texture_fill_j <= (image_size_j - image_skip_j) || !"Texture3D::load_sub_image_into_texture(): texture fill j was larger than sub image region");
00503 assert(texture_fill_k <= (image_size_k - image_skip_k) || !"Texture3D::load_sub_image_into_texture(): texture fill k was larger than sub image region");
00504
00505
00506
00507
00508
00509 m_image_skip_i = image_skip_i;
00510 m_image_skip_j = image_skip_j;
00511 m_image_skip_k = image_skip_k;
00512 m_image_size_i = image_size_i;
00513 m_image_size_j = image_size_j;
00514 m_image_size_k = image_size_k;
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 assert(pixels!= 0 || !"texture3D::load_sub_image_into_texture() - pixels was null");
00531 bind();
00532 setup_pixel_transfer();
00533
00534 glTexSubImage3D(
00535 m_texture_target
00536 , 0
00537 , texture_offset_i
00538 , texture_offset_j
00539 , texture_offset_k
00540 , texture_fill_i
00541 , texture_fill_j
00542 , texture_fill_k
00543 , m_format
00544 , m_type
00545 , pixels
00546 );
00547
00548 clear_pixel_transfer();
00549 }
00550
00557 template <typename T>
00558 void load(T const * pixels)
00559 {
00560 assert(pixels != 0 || !"Texture3D::load() - pixels are null");
00561 bind();
00562 setup_pixel_transfer();
00563
00564
00565
00566
00567
00568 int texture_offset_x = 0;
00569 int texture_offset_y = 0;
00570 int texture_offset_z = 0;
00571 glTexSubImage3D(
00572 m_texture_target
00573 , 0
00574 , texture_offset_x
00575 , texture_offset_y
00576 , texture_offset_z
00577 , m_texture_size_i
00578 , m_texture_size_j
00579 , m_texture_size_k
00580 , m_format
00581 , m_type
00582 , pixels
00583 );
00584
00585 clear_pixel_transfer();
00586 }
00587
00593 void set_repeating(bool flag)
00594 {
00595 bind();
00596 if(flag)
00597 {
00598 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
00599 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
00600 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_R, GL_REPEAT);
00601 }
00602 else
00603 {
00604 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00605 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00606 glTexParameteri( m_texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00607
00608
00609
00610 }
00611 }
00612
00623 bool is_valid_sampler_type(std::string const & sampler_type) const
00624 {
00625 if (m_cubic)
00626 {
00627 if (sampler_type!= "sampler3DCube" && sampler_type!="samplerCUBE")
00628 {
00629 std::cerr << "Texture3D::validate_sampler_type(): TextureRectangle attempted to bound to sampler type " << sampler_type << std::endl;
00630 return false;
00631 }
00632 }
00633 else
00634 {
00635 if (sampler_type!="sampler3D")
00636 {
00637 std::cerr << "Texture3D::validate_sampler_type(): Attempted to bound to sampler type " << sampler_type << std::endl;
00638 return false;
00639 }
00640 }
00641 return true;
00642 }
00643
00644 };
00645
00646 typedef boost::shared_ptr<Texture3D> texture3D_pointer;
00647
00648 }
00649 }
00650
00651
00652 #endif