00001 #ifndef OPENTISSUE_GPU_CG_CG_PROGRAM_H
00002 #define OPENTISSUE_GPU_CG_CG_PROGRAM_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/gpu/cg/cg_util.h>
00013
00014 #include<string>
00015 #include<map>
00016 #include<cassert>
00017
00018 namespace OpenTissue
00019 {
00020 namespace cg
00021 {
00022
00023 class Program
00024 {
00025 public:
00026
00027 typedef enum {vertex_program, fragment_program} program_type;
00028 typedef std::map<std::string, std::string> name_type_map;
00029
00030 protected:
00031
00032 program_type m_type;
00033 CGprogram m_program;
00034 CGprofile m_profile;
00035 CGcontext m_context;
00036 name_type_map m_uniforms;
00037 bool m_loaded;
00038
00039 public:
00040
00041 Program()
00042 : m_loaded(false)
00043 {}
00044
00045 public:
00046
00047 void enable()
00048 {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 cgGLEnableProfile(m_profile);
00067 cgGLBindProgram(m_program);
00068 gl::gl_check_errors("Program::enable() - at the end");
00069 }
00070
00071 void disable()
00072 {
00073 cgGLUnbindProgram( m_profile );
00074 cgGLDisableProfile( m_profile );
00075 gl::gl_check_errors("Program::disable()");
00076
00077 glDisable(GL_TEXTURE_2D);
00078 glDisable(GL_TEXTURE_3D);
00079 }
00080
00081 public:
00082
00083 bool load_from_text(program_type type,std::string const & program_text)
00084 {
00085 m_context = OpenTissue::cg::context();
00086 if(type==vertex_program)
00087 {
00088 m_profile = OpenTissue::cg::vertex_profile();
00089 if(OpenTissue::cg::vertex_program())
00090 OpenTissue::cg::vertex_program()->m_loaded = false;
00091 }
00092 else
00093 {
00094 m_profile = OpenTissue::cg::fragment_profile();
00095 if(OpenTissue::cg::fragment_program())
00096 OpenTissue::cg::fragment_program()->m_loaded = false;
00097 }
00098 const char *cstr = program_text.c_str();
00099 m_program = cgCreateProgram(m_context, CG_SOURCE, cstr, m_profile, 0, 0);
00100
00101 if (m_program == 0)
00102 {
00103 std::cerr << "Program::load_from_text(): could not create program" << std::endl;
00104 return false;
00105 }
00106 cgGLLoadProgram( m_program );
00107 m_uniforms = get_uniforms_map();
00108 m_loaded = true;
00109 gl::gl_check_errors("After Program::load_from_text()");
00110 return true;
00111 };
00112
00113 bool load_from_file(program_type type,std::string const & filename)
00114 {
00115 m_context = OpenTissue::cg::context();
00116
00117 if(type==vertex_program)
00118 {
00119 m_profile = OpenTissue::cg::vertex_profile();
00120 if(OpenTissue::cg::vertex_program())
00121 OpenTissue::cg::vertex_program()->m_loaded = false;
00122 }
00123 else
00124 {
00125 m_profile = OpenTissue::cg::fragment_profile();
00126 if(OpenTissue::cg::fragment_program())
00127 OpenTissue::cg::fragment_program()->m_loaded = false;
00128 }
00129 const char *cstr = filename.c_str();
00130 m_program = cgCreateProgramFromFile(m_context, CG_SOURCE, cstr, m_profile, 0, 0);
00131 if (m_program == 0)
00132 {
00133 std::cerr << "Program::load_from_file("<<filename<<"): could not create program" << std::endl;
00134 return false;
00135 }
00136 cgGLLoadProgram( m_program );
00137 m_uniforms = get_uniforms_map();
00138 m_loaded = true;
00139 gl::gl_check_errors("After Program::load_from_file()");
00140 return true;
00141 };
00142
00143 bool is_program_loaded()const
00144 {
00145 if(m_context != OpenTissue::cg::context())
00146 return false;
00147 return m_loaded;
00148 }
00149
00150 CGprogram get_program_ID(){ return m_program; }
00151
00152 protected:
00153
00154 struct RecurseParams
00155 {
00156 void operator()( name_type_map & map, CGparameter param )
00157 {
00158 if (!param)
00159 return;
00160
00161 do
00162 {
00163 switch ( cgGetParameterType(param) )
00164 {
00165 case CG_STRUCT:
00166 RecurseParams()( map, cgGetFirstStructParameter( param ) );
00167 break;
00168 case CG_ARRAY:
00169 {
00170 int size = cgGetArraySize( param, 0 );
00171 for ( int i = 0; i < size; ++i )
00172 RecurseParams()( map, cgGetArrayParameter( param, i ) );
00173 }
00174 break;
00175 case CG_BOOL:case CG_BOOL1:case CG_BOOL1x1: case CG_BOOL1x2:case CG_BOOL1x3:case CG_BOOL1x4:
00176 case CG_BOOL2:case CG_BOOL2x1: case CG_BOOL2x2:case CG_BOOL2x3:case CG_BOOL2x4:
00177 case CG_BOOL3:case CG_BOOL3x1: case CG_BOOL3x2:case CG_BOOL3x3:case CG_BOOL3x4:
00178 case CG_BOOL4:case CG_BOOL4x1: case CG_BOOL4x2:case CG_BOOL4x3:case CG_BOOL4x4:
00179 case CG_FIXED:case CG_FIXED1:case CG_FIXED1x1: case CG_FIXED1x2:case CG_FIXED1x3:case CG_FIXED1x4:
00180 case CG_FIXED2:case CG_FIXED2x1: case CG_FIXED2x2:case CG_FIXED2x3:case CG_FIXED2x4:
00181 case CG_FIXED3:case CG_FIXED3x1: case CG_FIXED3x2:case CG_FIXED3x3:case CG_FIXED3x4:
00182 case CG_FIXED4:case CG_FIXED4x1: case CG_FIXED4x2:case CG_FIXED4x3:case CG_FIXED4x4:
00183 case CG_FLOAT:case CG_FLOAT1:case CG_FLOAT1x1: case CG_FLOAT1x2:case CG_FLOAT1x3:case CG_FLOAT1x4:
00184 case CG_FLOAT2:case CG_FLOAT2x1: case CG_FLOAT2x2:case CG_FLOAT2x3:case CG_FLOAT2x4:
00185 case CG_FLOAT3:case CG_FLOAT3x1: case CG_FLOAT3x2:case CG_FLOAT3x3:case CG_FLOAT3x4:
00186 case CG_FLOAT4:case CG_FLOAT4x1: case CG_FLOAT4x2:case CG_FLOAT4x3:case CG_FLOAT4x4:
00187 case CG_HALF:case CG_HALF1:case CG_HALF1x1: case CG_HALF1x2:case CG_HALF1x3:case CG_HALF1x4:
00188 case CG_HALF2:case CG_HALF2x1: case CG_HALF2x2:case CG_HALF2x3:case CG_HALF2x4:
00189 case CG_HALF3:case CG_HALF3x1: case CG_HALF3x2:case CG_HALF3x3:case CG_HALF3x4:
00190 case CG_HALF4:case CG_HALF4x1: case CG_HALF4x2:case CG_HALF4x3:case CG_HALF4x4:
00191 case CG_INT:case CG_INT1:case CG_INT1x1: case CG_INT1x2:case CG_INT1x3:case CG_INT1x4:
00192 case CG_INT2:case CG_INT2x1: case CG_INT2x2:case CG_INT2x3:case CG_INT2x4:
00193 case CG_INT3:case CG_INT3x1: case CG_INT3x2:case CG_INT3x3:case CG_INT3x4:
00194 case CG_INT4:case CG_INT4x1: case CG_INT4x2:case CG_INT4x3:case CG_INT4x4:
00195 case CG_SAMPLERRECT:case CG_SAMPLER1D:case CG_SAMPLER2D:case CG_SAMPLER3D:
00196 case CG_SAMPLERCUBE:case CG_TYPE_START_ENUM:case CG_UNKNOWN_TYPE:
00197 case CG_TEXTURE:case CG_PROGRAM_TYPE:case CG_STRING:
00199
00200
00201
00202
00203
00204
00205
00206 default:
00207 if ( cgGetParameterVariability( param ) == CG_UNIFORM )
00208 {
00209
00210 map[cgGetParameterName(param)] = cgGetTypeString(cgGetParameterType(param));
00211
00212 }
00213 break;
00214 }
00215 }
00216 while((param = cgGetNextParameter(param)) != 0);
00217 }
00218 };
00219
00220 public:
00221
00222 name_type_map get_uniforms_map()
00223 {
00224 name_type_map map;
00225 CGparameter cgp = cgGetFirstParameter( m_program, CG_PROGRAM );
00226 RecurseParams()( map, cgp );
00227 return map;
00228 }
00229
00230 protected:
00231
00232 #ifndef NDEBUG
00233 template<typename texture_type>
00234 CGparameter get_texture_param( std::string const & name , texture_type const & texture) const
00235 {
00236 CGparameter param = cgGetNamedParameter( m_program, name.c_str() );
00237 if ( param == 0 )
00238 {
00239 std::cerr << "Program::get_texture_param(): Variable " << name.c_str() << " was not found or illegal." << std::endl;
00240 return 0;
00241 }
00242 name_type_map::const_iterator lookup = m_uniforms.find( name );
00243 assert( lookup != m_uniforms.end() || !"Program::get_texture_param(): The uniform map does not correspond with the Cg runtime." );
00244 std::string sampler_type(cgGetTypeString(cgGetParameterType(param)));
00245 if(!texture.is_valid_sampler_type(sampler_type))
00246 {
00247 std::cerr << "Program::get_texture_param(): Texture variable " << name.c_str() << " was not compatible with texture." << std::endl;
00248 return 0;
00249 };
00250 return param;
00251 }
00252 #else
00253 template<typename texture_type>
00254 CGparameter get_texture_param( std::string const & name , texture_type const & ) const
00255 {
00256 return cgGetNamedParameter( m_program, name.c_str() );
00257 }
00258 #endif
00259
00260 CGparameter get_uniform_param( std::string const & name ) const
00261 {
00262 #ifndef NDEBUG
00263 CGparameter param = cgGetNamedParameter( m_program, name.c_str() );
00264 if ( param == 0 )
00265 {
00266 std::cout << "Program::get_uniform_param(): Uniform variable " << name.c_str() << " was not found or illegal." << std::endl;
00267 return 0;
00268 }
00269 name_type_map::const_iterator lookup = m_uniforms.find( name );
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 return param;
00280 #else
00281 return cgGetNamedParameter( m_program, name.c_str() );
00282 #endif
00283 }
00284
00285 CGparameter get_attribute_param( std::string const & name ) const
00286 {
00287 #ifndef NDEBUG
00288 CGparameter param = cgGetNamedParameter( m_program, name.c_str() );
00289 if ( param == 0 )
00290 {
00291 std::cout << "Program::get_attribute_param(): Attribute variable " << name.c_str() << " was not found or illegal." << std::endl;
00292 return 0;
00293 }
00294 return param;
00295 #else
00296 return cgGetNamedParameter( m_program, name.c_str() );
00297 #endif
00298 }
00299
00300 public:
00301
00302 void set_modelview_projection_matrix(std::string const & name = "ModelViewProj")
00303 {
00304 CGparameter param = get_uniform_param( name );
00305 cgGLSetStateMatrixParameter ( param, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY );
00306 gl::gl_check_errors("After Program::set_modelview_projection_matrix()");
00307 }
00308
00309 void set_modelview_inverse_transpose(std::string const & name = "ModelViewIT")
00310 {
00311 CGparameter param = get_uniform_param( name );
00312 cgGLSetStateMatrixParameter ( param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE_TRANSPOSE );
00313 gl::gl_check_errors("After Program::set_modelview_inverse_transpose()");
00314 }
00315
00316 void set_modelview_inverse_matrix(std::string const & name = "ModelViewI")
00317 {
00318 CGparameter param = get_uniform_param( name );
00319 cgGLSetStateMatrixParameter ( param, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE );
00320 gl::gl_check_errors("After Program::set_float_param()");
00321 }
00322
00323 void set_texture_matrix(std::string const & name = "TexMatrix")
00324 {
00325 CGparameter param = get_uniform_param( name );
00326 cgGLSetStateMatrixParameter ( param, CG_GL_TEXTURE_MATRIX, CG_GL_MATRIX_IDENTITY );
00327 gl::gl_check_errors("After Program::set_texture_matrix()");
00328 }
00329
00330 public:
00331
00332 void set_float_param(std::string const & name, float const value)
00333 {
00334 CGparameter param = get_uniform_param(name);
00335 cgGLSetParameter1f(param, value);
00336 gl::gl_check_errors("After Program::set_float_param()");
00337 }
00338
00339 void set_float_param(std::string const & name, float const value0, float const value1)
00340 {
00341 CGparameter param = get_uniform_param( name );
00342 cgGLSetParameter2f(param, value0, value1);
00343 gl::gl_check_errors("After Program::set_float_param()");
00344 }
00345
00346 void set_float_param(std::string const & name, float const value0, float const value1, float const value2)
00347 {
00348 CGparameter param = get_uniform_param( name );
00349 cgGLSetParameter3f(param, value0, value1, value2);
00350 gl::gl_check_errors("After Program::set_float_param()");
00351 }
00352
00353 void set_float_param(std::string const & name, float const value0, float const value1, float const value2, float const value3)
00354 {
00355 CGparameter param = get_uniform_param( name );
00356 cgGLSetParameter4f(param, value0, value1, value2, value3);
00357 gl::gl_check_errors("After Program::set_float_param()");
00358 }
00359
00360 void set_float_array_param(std::string const & name, int const number_of_elements, float const * values)
00361 {
00362 CGparameter param = get_uniform_param( name );
00363 int start_index = 0;
00364 cgGLSetParameterArray1f(param, start_index, number_of_elements, values);
00365 gl::gl_check_errors("After Program::set_float_array_param()");
00366 }
00367
00368 void set_float3_array_param(std::string const & name, int const number_of_elements, float const * values)
00369 {
00370 CGparameter param = get_uniform_param( name );
00371 int start_index = 0;
00372 cgGLSetParameterArray3f(param, start_index, number_of_elements, values );
00373 gl::gl_check_errors("After Program::set_float3_array_param()");
00374 }
00375
00376 void set_floatNxN_array_param(std::string const & name, int number_of_elements, float const * values)
00377 {
00378 CGparameter param = get_uniform_param( name );
00379 int start_index = 0;
00380 cgGLSetMatrixParameterArrayfr( param, start_index, number_of_elements, values );
00381 gl::gl_check_errors("After Program::set_float4x4_array_param()");
00382 }
00383
00384 void enable_client_state(std::string const & name)
00385 {
00386 CGparameter param = get_attribute_param( name );
00387 cgGLEnableClientState(param);
00388 gl::gl_check_errors("After Program::enable_client_state()");
00389 }
00390
00391 void disable_client_state(std::string const & name)
00392 {
00393 CGparameter param = get_attribute_param( name );
00394 cgGLDisableClientState(param);
00395 gl::gl_check_errors("After Program::disable_client_state()");
00396 }
00397
00398 public:
00399
00400 template<typename texture_pointer>
00401 void set_input_texture( std::string const & name, texture_pointer texture )
00402 {
00403 texture->bind();
00404 gl::gl_check_errors("Program::set_input_texture() - texture->bind();");
00405
00406 CGparameter param = get_texture_param(name, *texture );
00407 gl::gl_check_errors("Program::set_input_texture() - cgGLEnableTextureParameter( param ) );");
00408
00409 cgGLSetTextureParameter( param, texture->get_texture_ID() );
00410 gl::gl_check_errors("Program::set_input_texture() - cgGLSetTextureParameter( param, texture->get_texture_ID() );");
00411
00412 cgGLEnableTextureParameter(param);
00413 }
00414
00415 void set_attribute_pointer( std::string const & name, int size, int type, unsigned int stride, const void *pointer)
00416 {
00417 CGparameter param = get_attribute_param( name );
00418 cgGLSetParameterPointer(param, size, type, stride, (GLvoid*)(pointer));
00419 gl::gl_check_errors("Program::set_attribute_pointer()");
00420 }
00421 };
00422
00423 }
00424 }
00425
00426
00427 #endif