00001 #ifndef OPENTISSUE_UTILITY_VOLUME_RENDERING_RAY_CAST_SHADER_VOLUME_RENDERING_RAY_CAST_SHADER_H
00002 #define OPENTISSUE_UTILITY_VOLUME_RENDERING_RAY_CAST_SHADER_VOLUME_RENDERING_RAY_CAST_SHADER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/gpu/cg/cg_program.h>
00013 #include <OpenTissue/utility/gl/gl_matrix_util.h>
00014 #include <OpenTissue/gpu/texture/texture_create_texture3D.h>
00015 #include <OpenTissue/gpu/texture/texture_create_texture2D.h>
00016 #include <OpenTissue/gpu/texture/texture_show_texture2D.h>
00017 #include <OpenTissue/core/geometry/geometry_aabb.h>
00018 #include <OpenTissue/utility/volume_rendering/volume_rendering_volume_shader.h>
00019 #include <OpenTissue/utility/gl/gl_frame_buffer_object.h>
00020
00021 #include <string>
00022
00023
00024 namespace OpenTissue
00025 {
00026 namespace volume_rendering
00027 {
00031 template<typename math_types>
00032 class RayCastShader
00033 : public VolumeShader< RayCastShader<math_types> >
00034 {
00035 public:
00036
00037 typedef typename math_types::real_type real_type;
00038 typedef typename math_types::vector3_type vector3_type;
00039 typedef geometry::AABB<math_types> aabb_type;
00040
00041 protected:
00042
00043 OpenTissue::texture::texture3D_pointer m_volume_texture;
00044 OpenTissue::texture::texture2D_pointer m_texture[4];
00045 gl::FramebufferObject m_fbo;
00046
00047 cg::Program m_main_pass_program;
00048 cg::Program m_ray_direction_program;
00049 cg::Program m_pass_through_program;
00050
00051 real_type m_delta_t;
00052 unsigned int m_iterations;
00053 unsigned int m_inner_iterations;
00054 unsigned int m_outer_iterations;
00055
00056 int m_write;
00057 int m_read;
00058 int m_ray_map;
00059 int m_entry_map;
00060
00061 public:
00062
00063 unsigned int total_iterations() { return m_iterations; }
00064 unsigned int const & total_iterations() const { return m_iterations; }
00065 unsigned int inner_iterations() { return m_inner_iterations; }
00066 unsigned int const & inner_iterations() const { return m_inner_iterations; }
00067
00068 protected:
00069
00070 template<typename tile_type>
00071 void draw_aabb(tile_type const & tile, real_type delta_t, real_type t)
00072 {
00073 real_type min_x = tile.m_aabb_min_x;
00074 real_type min_y = tile.m_aabb_min_y;
00075 real_type min_z = tile.m_aabb_min_z;
00076
00077 real_type max_x = min_x + tile.m_aabb_width;
00078 real_type max_y = min_y + tile.m_aabb_height;
00079 real_type max_z = min_z + tile.m_aabb_depth;
00080
00081 real_type min_r = (min_x - tile.m_tile_min_x)/tile.m_tile_width;
00082 real_type max_r = (max_x - tile.m_tile_min_x)/tile.m_tile_width;
00083 real_type min_g = (min_y - tile.m_tile_min_y)/tile.m_tile_height;
00084 real_type max_g = (max_y - tile.m_tile_min_y)/tile.m_tile_height;
00085 real_type min_b = (min_z - tile.m_tile_min_z)/tile.m_tile_depth;
00086 real_type max_b = (max_z - tile.m_tile_min_z)/tile.m_tile_depth;
00087
00088 glBegin(GL_POLYGON);
00089 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, max_b); glNormal3f( 0, 0, 1); glVertex3f( min_x, min_y, max_z);
00090 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, max_b); glNormal3f( 0, 0, 1); glVertex3f( max_x, min_y, max_z);
00091 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, max_b); glNormal3f( 0, 0, 1); glVertex3f( max_x, max_y, max_z);
00092 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, max_b); glNormal3f( 0, 0, 1); glVertex3f( min_x, max_y, max_z);
00093 glEnd();
00094 glBegin(GL_POLYGON);
00095 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, max_b); glNormal3f( 1, 0, 0); glVertex3f( max_x, min_y, max_z);
00096 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, min_b); glNormal3f( 1, 0, 0); glVertex3f( max_x, min_y, min_z);
00097 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, min_b); glNormal3f( 1, 0, 0); glVertex3f( max_x, max_y, min_z);
00098 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, max_b); glNormal3f( 1, 0, 0); glVertex3f( max_x, max_y, max_z);
00099 glEnd();
00100 glBegin(GL_POLYGON);
00101 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, max_b); glNormal3f( 0, 1, 0); glVertex3f( min_x, max_y, max_z);
00102 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, max_b); glNormal3f( 0, 1, 0); glVertex3f( max_x, max_y, max_z);
00103 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, min_b); glNormal3f( 0, 1, 0); glVertex3f( max_x, max_y, min_z);
00104 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, min_b); glNormal3f( 0, 1, 0); glVertex3f( min_x, max_y, min_z);
00105 glEnd();
00106 glBegin(GL_POLYGON);
00107 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, min_b); glNormal3f( 0, 0,-1); glVertex3f( min_x, min_y, min_z);
00108 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, min_b); glNormal3f( 0, 0,-1); glVertex3f( min_x, max_y, min_z);
00109 glTexCoord2f(delta_t, t); glColor3f( max_r, max_g, min_b); glNormal3f( 0, 0,-1); glVertex3f( max_x, max_y, min_z);
00110 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, min_b); glNormal3f( 0, 0,-1); glVertex3f( max_x, min_y, min_z);
00111 glEnd();
00112 glBegin(GL_POLYGON);
00113 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, min_b); glNormal3f( 0,-1, 0); glVertex3f( min_x, min_y, min_z);
00114 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, min_b); glNormal3f( 0,-1, 0); glVertex3f( max_x, min_y, min_z);
00115 glTexCoord2f(delta_t, t); glColor3f( max_r, min_g, max_b); glNormal3f( 0,-1, 0); glVertex3f( max_x, min_y, max_z);
00116 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, max_b); glNormal3f( 0,-1, 0); glVertex3f( min_x, min_y, max_z);
00117 glEnd();
00118 glBegin(GL_POLYGON);
00119 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, min_b); glNormal3f(-1, 0, 0); glVertex3f( min_x, min_y, min_z);
00120 glTexCoord2f(delta_t, t); glColor3f( min_r, min_g, max_b); glNormal3f(-1, 0, 0); glVertex3f( min_x, min_y, max_z);
00121 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, max_b); glNormal3f(-1, 0, 0); glVertex3f( min_x, max_y, max_z);
00122 glTexCoord2f(delta_t, t); glColor3f( min_r, max_g, min_b); glNormal3f(-1, 0, 0); glVertex3f( min_x, max_y, min_z);
00123 glEnd();
00124 };
00125
00126 public:
00127
00128 RayCastShader()
00129 : m_iterations(32)
00130 {}
00131
00132 ~RayCastShader()
00133 {
00134 gl::FramebufferObject::disable();
00135 }
00136
00137 void init()
00138 {
00139 static const GLenum buffer[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
00140 using std::sqrt;
00141 GLfloat viewport[4];
00142 glGetFloatv( GL_VIEWPORT, viewport );
00143 int width = static_cast<int>( viewport[ 2 ] );
00144 int height = static_cast<int>( viewport[ 3 ] );
00145 for(unsigned int i=0;i<4;++i)
00146 m_texture[i] = OpenTissue::texture::create_float_texture_rectangle( width, height, 4, 0 );
00147 m_fbo.bind();
00148 for(unsigned int i=0;i<4;++i)
00149 m_fbo.attach_texture( buffer[i], m_texture[i] );
00150 m_fbo.is_valid();
00151 gl::FramebufferObject::disable();
00152 }
00153
00154 bool front2back()const{ return true; }
00155
00156 template<typename texture2d_pointer>
00157 void pre_render(texture2d_pointer color_table_texture)
00158 {
00159 glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT );
00160
00161 static const GLenum buffer[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
00162 m_fbo.bind();
00163 glDisable( GL_LIGHTING );
00164 glDisable( GL_ALPHA_TEST );
00165 glDisable( GL_SCISSOR_TEST );
00166 glDisable( GL_STENCIL_TEST );
00167 glDisable( GL_BLEND );
00168 glDisable( GL_DEPTH_TEST );
00169 glEnable( GL_CULL_FACE );
00170 glClearColor( 0, 0, 0, 0 );
00171
00172 m_write = 0;
00173 m_read = 1;
00174 m_entry_map = 2;
00175 m_ray_map = 3;
00176
00177 glDrawBuffer( buffer[m_write] );
00178 glClear( GL_COLOR_BUFFER_BIT );
00179 glDrawBuffer( buffer[m_read] );
00180 glClear( GL_COLOR_BUFFER_BIT );
00181
00182 static std::string path = opentissue_path + "/OpenTissue/utility/volume_rendering/ray_cast_shader";
00183 if(!m_pass_through_program.is_program_loaded())
00184 m_pass_through_program.load_from_file(cg::Program::fragment_program,path + "/fp_pass_through.cg");
00185 if(!m_ray_direction_program.is_program_loaded())
00186 m_ray_direction_program.load_from_file(cg::Program::fragment_program,path + "/fp_ray_direction.cg");
00187 if(!m_main_pass_program.is_program_loaded())
00188 m_main_pass_program.load_from_file(cg::Program::fragment_program,path + "/fp_main_pass.cg");
00189 m_main_pass_program.set_input_texture( "color_table" , color_table_texture );
00190 }
00191
00192 template<typename tile_type>
00193 void render(tile_type const & tile)
00194 {
00195 using std::ceil;
00196
00197 static const GLenum buffer[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
00198
00199 float diagonal = sqrt(3.0);
00200 m_delta_t = diagonal / m_iterations;
00201 m_inner_iterations = 8;
00202 m_outer_iterations = static_cast<unsigned int> ( ceil( 1.f * m_iterations / m_inner_iterations ) );
00203 real_type delta = m_delta_t * m_inner_iterations;
00204
00205 glDrawBuffer( buffer[m_entry_map] );
00206 glClear( GL_COLOR_BUFFER_BIT );
00207 glCullFace( GL_BACK );
00208 m_pass_through_program.enable();
00209 draw_aabb(tile,0,0);
00210 m_pass_through_program.disable();
00211
00212 glDrawBuffer(buffer[m_ray_map]);
00213 glClear( GL_COLOR_BUFFER_BIT );
00214 glCullFace( GL_FRONT );
00215 m_ray_direction_program.set_input_texture( "entry_map", m_texture[m_entry_map] );
00216 m_ray_direction_program.enable();
00217 draw_aabb(tile,0,0);
00218 m_ray_direction_program.disable();
00219
00220 glCullFace( GL_BACK );
00221 m_main_pass_program.set_input_texture( "ray_map", m_texture[m_ray_map] );
00222 m_main_pass_program.set_input_texture( "volume", tile.m_volume_texture );
00223 m_main_pass_program.enable();
00224 for ( unsigned int i = 0; i < m_outer_iterations; ++i )
00225 {
00226 glDrawBuffer (buffer[m_write]);
00227 m_main_pass_program.set_input_texture( "image", m_texture[m_read] );
00228 draw_aabb(tile,m_delta_t, i*delta);
00229 std::swap(m_write,m_read);
00230 }
00231 m_main_pass_program.disable();
00232
00233
00234
00235
00236
00237
00238 }
00239
00240 void post_render()
00241 {
00242 gl::FramebufferObject::disable();
00243 glPopAttrib();
00244 show_texture2D(m_texture[m_read]);
00245 }
00246 };
00247
00248 }
00249 }
00250
00251
00252 #endif
00253