File indexing completed on 2026-04-09 07:49:38
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008 #include "ssys.h"
0009
0010
0011 struct SGLFW_Program
0012 {
0013 static constexpr const char* _LEVEL = "SGLFW_Program__LEVEL" ;
0014 static constexpr const char* MVP_KEYS = "ModelViewProjection,MVP" ;
0015
0016 int level ;
0017 const char* dir ;
0018 const char* vtx_attname ;
0019 const char* nrm_attname ;
0020 const char* ins_attname ;
0021 const char* mvp_uniname ;
0022
0023 const char* vertex_shader_text ;
0024 const char* geometry_shader_text ;
0025 const char* fragment_shader_text ;
0026
0027 GLuint program ;
0028 GLint mvp_location ;
0029 const float* mvp ;
0030 bool dump ;
0031
0032 SGLFW_Program(
0033 const char* _dir,
0034 const char* _vtx_attname,
0035 const char* _nrm_attname,
0036 const char* _ins_attname,
0037 const char* _mvp_uniname,
0038 const float* _mvp
0039 );
0040 void init();
0041
0042 void createFromDir(const char* _dir);
0043 void createFromText(const char* vertex_shader_text, const char* geometry_shader_text, const char* fragment_shader_text );
0044 void use() const ;
0045
0046 GLint getUniformLocation(const char* name) const ;
0047 GLint getAttribLocation(const char* name) const ;
0048
0049 GLint findUniformLocation(const char* keys, char delim ) const ;
0050 void locateMVP(const char* key, const float* mvp );
0051 void updateMVP() const ;
0052
0053 static void UniformMatrix4fv( GLint loc, const float* vv, bool dump );
0054 static void Uniform4fv( GLint loc, const float* vv, bool dump );
0055
0056 void enableVertexAttribArray( const char* name, const char* spec, bool dump=false ) const ;
0057 void enableVertexAttribArray_OfTransforms( const char* name ) const ;
0058
0059 static void Print_shader_info_log(unsigned id);
0060
0061 template<typename T>
0062 static std::string Desc(const T* tt, int num);
0063
0064 };
0065
0066 inline SGLFW_Program::SGLFW_Program(
0067 const char* _dir,
0068 const char* _vtx_attname,
0069 const char* _nrm_attname,
0070 const char* _ins_attname,
0071 const char* _mvp_uniname,
0072 const float* _mvp
0073 )
0074 :
0075 level(ssys::getenvint(_LEVEL, 0)),
0076 dir( _dir ? strdup(_dir) : nullptr ),
0077 vtx_attname( _vtx_attname ? strdup(_vtx_attname) : nullptr ),
0078 nrm_attname( _nrm_attname ? strdup(_nrm_attname) : nullptr ),
0079 ins_attname( _ins_attname ? strdup(_ins_attname) : nullptr ),
0080 mvp_uniname( _mvp_uniname ? strdup(_mvp_uniname) : nullptr ),
0081 vertex_shader_text(nullptr),
0082 geometry_shader_text(nullptr),
0083 fragment_shader_text(nullptr),
0084 program(0),
0085 mvp_location(-1),
0086 mvp(_mvp),
0087 dump(false)
0088 {
0089 init();
0090 }
0091
0092
0093 inline void SGLFW_Program::init()
0094 {
0095 if(dir) createFromDir(dir) ;
0096 use();
0097 if(mvp_uniname)
0098 {
0099 mvp_location = getUniformLocation(mvp_uniname);
0100 assert( mvp_location > -1 );
0101 }
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 inline void SGLFW_Program::locateMVP(const char* key, const float* mvp_ )
0118 {
0119 if(level > 0) std::cout << "SGLFW_Program::locateMVP backwards compat" << std::endl ;
0120 mvp_location = getUniformLocation(key);
0121 assert( mvp_location > -1 );
0122 mvp = mvp_ ;
0123 }
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 inline void SGLFW_Program::updateMVP() const
0139 {
0140 if( mvp_location <= -1 ) return ;
0141 assert( mvp != nullptr );
0142 UniformMatrix4fv(mvp_location, mvp, dump );
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 inline void SGLFW_Program::createFromDir(const char* _dir)
0157 {
0158 const char* dir = U::Resolve(_dir);
0159
0160 if(level > 0) std::cout
0161 << "SGLFW_Program::createFromDir"
0162 << " _dir " << ( _dir ? _dir : "-" )
0163 << " dir " << ( dir ? dir : "-" )
0164 << "\n"
0165 ;
0166
0167
0168 vertex_shader_text = U::ReadString(dir, "vert.glsl");
0169 geometry_shader_text = U::ReadString(dir, "geom.glsl");
0170 fragment_shader_text = U::ReadString(dir, "frag.glsl");
0171
0172 if(level > 0) std::cout
0173 << "SGLFW_Program::createFromDir"
0174 << " _dir " << ( _dir ? _dir : "-" )
0175 << " dir " << ( dir ? dir : "-" )
0176 << " vertex_shader_text " << ( vertex_shader_text ? "YES" : "NO" )
0177 << " geometry_shader_text " << ( geometry_shader_text ? "YES" : "NO" )
0178 << " fragment_shader_text " << ( fragment_shader_text ? "YES" : "NO" )
0179 << std::endl
0180 ;
0181
0182 createFromText( vertex_shader_text, geometry_shader_text, fragment_shader_text );
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 inline void SGLFW_Program::createFromText(const char* vertex_shader_text, const char* geometry_shader_text, const char* fragment_shader_text )
0206 {
0207 if(level > 0) std::cout << "[SGLFW_Program::createFromText level " << level << std::endl ;
0208 if(level > 1) std::cout << " vertex_shader_text " << std::endl << ( vertex_shader_text ? vertex_shader_text : "-" ) << std::endl ;
0209 if(level > 1) std::cout << " geometry_shader_text " << std::endl << ( geometry_shader_text ? geometry_shader_text : "-" ) << std::endl ;
0210 if(level > 1) std::cout << " fragment_shader_text " << std::endl << ( fragment_shader_text ? fragment_shader_text : "-" ) << std::endl ;
0211
0212 bool expect = vertex_shader_text && fragment_shader_text ;
0213 assert( expect );
0214 if(!expect) std::raise(SIGINT);
0215
0216
0217 int params = -1;
0218 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); SGLFW__check(__FILE__, __LINE__);
0219 glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL); SGLFW__check(__FILE__, __LINE__);
0220 glCompileShader(vertex_shader); SGLFW__check(__FILE__, __LINE__);
0221 glGetShaderiv (vertex_shader, GL_COMPILE_STATUS, ¶ms);
0222 if (GL_TRUE != params) Print_shader_info_log(vertex_shader) ;
0223
0224 GLuint geometry_shader = 0 ;
0225 if( geometry_shader_text )
0226 {
0227 geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); SGLFW__check(__FILE__, __LINE__);
0228 glShaderSource(geometry_shader, 1, &geometry_shader_text, NULL); SGLFW__check(__FILE__, __LINE__);
0229 glCompileShader(geometry_shader); SGLFW__check(__FILE__, __LINE__);
0230 glGetShaderiv (geometry_shader, GL_COMPILE_STATUS, ¶ms);
0231 if (GL_TRUE != params) Print_shader_info_log(geometry_shader) ;
0232 }
0233
0234 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); SGLFW__check(__FILE__, __LINE__);
0235 glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL); SGLFW__check(__FILE__, __LINE__);
0236 glCompileShader(fragment_shader); SGLFW__check(__FILE__, __LINE__);
0237 glGetShaderiv (fragment_shader, GL_COMPILE_STATUS, ¶ms);
0238 if (GL_TRUE != params) Print_shader_info_log(fragment_shader) ;
0239
0240 program = glCreateProgram(); SGLFW__check(__FILE__, __LINE__);
0241 glAttachShader(program, vertex_shader); SGLFW__check(__FILE__, __LINE__);
0242 if( geometry_shader > 0 )
0243 {
0244 glAttachShader(program, geometry_shader); SGLFW__check(__FILE__, __LINE__);
0245 }
0246 glAttachShader(program, fragment_shader); SGLFW__check(__FILE__, __LINE__);
0247 glLinkProgram(program); SGLFW__check(__FILE__, __LINE__);
0248
0249 if(level > 0) std::cout << "]SGLFW_Program::createFromText level " << level << std::endl ;
0250 }
0251
0252 inline void SGLFW_Program::use() const
0253 {
0254 glUseProgram(program);
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 inline GLint SGLFW_Program::getUniformLocation(const char* name) const
0268 {
0269 GLint loc = glGetUniformLocation(program, name); SGLFW__check(__FILE__, __LINE__, name, loc, "glGetUniformLocation/m" );
0270 return loc ;
0271 }
0272
0273 inline GLint SGLFW_Program::getAttribLocation(const char* name) const
0274 {
0275 GLint loc = glGetAttribLocation(program, name); SGLFW__check(__FILE__, __LINE__, name, loc, "glGetAttribLocation/m" );
0276 return loc ;
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 inline GLint SGLFW_Program::findUniformLocation(const char* keys, char delim ) const
0292 {
0293 std::vector<std::string> kk ;
0294
0295 std::stringstream ss;
0296 ss.str(keys) ;
0297 std::string key;
0298 while (std::getline(ss, key, delim)) kk.push_back(key) ;
0299
0300 GLint loc = -1 ;
0301
0302 int num_key = kk.size();
0303 for(int i=0 ; i < num_key ; i++)
0304 {
0305 const char* k = kk[i].c_str();
0306 loc = getUniformLocation(k);
0307 if(loc > -1) break ;
0308 }
0309 return loc ;
0310 }
0311
0312
0313
0314 template<typename T>
0315 inline std::string SGLFW_Program::Desc(const T* tt, int num)
0316 {
0317 std::stringstream ss ;
0318 for(int i=0 ; i < num ; i++)
0319 ss
0320 << ( i % 4 == 0 && num > 4 ? ".\n" : "" )
0321 << " " << std::fixed << std::setw(10) << std::setprecision(4) << tt[i]
0322 << ( i == num-1 && num > 4 ? ".\n" : "" )
0323 ;
0324
0325 std::string s = ss.str();
0326 return s ;
0327 }
0328
0329 inline void SGLFW_Program::UniformMatrix4fv( GLint loc, const float* vv, bool dump )
0330 {
0331 if(dump) std::cout
0332 << "SGLFW_Program::UniformMatrix4fv"
0333 << " loc " << loc
0334 << std::endl
0335 << Desc(vv, 16)
0336 << std::endl
0337 ;
0338
0339 assert( loc > -1 );
0340 glUniformMatrix4fv(loc, 1, GL_FALSE, (const GLfloat*)vv );
0341 }
0342
0343 inline void SGLFW_Program::Uniform4fv( GLint loc, const float* vv, bool dump )
0344 {
0345 if(dump) std::cout
0346 << "SGLFW_Program::Uniform4fv"
0347 << " loc " << loc
0348 << std::endl
0349 << Desc(vv, 4)
0350 << std::endl
0351 ;
0352
0353 assert( loc > -1 );
0354 glUniform4fv(loc, 1, (const GLfloat*)vv );
0355 }
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 inline void SGLFW_Program::enableVertexAttribArray( const char* name, const char* spec, bool dump ) const
0385 {
0386 if(dump) std::cout << "SGLFW_Program::enableVertexAttribArray name [" << name << "]" << std::endl ;
0387
0388 SGLFW_Attrib att(name, spec);
0389
0390 att.index = getAttribLocation( name ); SGLFW__check(__FILE__, __LINE__, name, att.index, "getAttribLocation" );
0391
0392 if(dump) std::cout << "SGLFW_Program::enableVertexAttribArray att.desc [" << att.desc() << "]" << std::endl ;
0393
0394 glEnableVertexAttribArray(att.index); SGLFW__check(__FILE__, __LINE__, name, att.index, "glEnableVertexAttribArray" );
0395
0396 assert( att.integer_attribute == false );
0397
0398 glVertexAttribPointer(att.index, att.size, att.type, att.normalized, att.stride, att.byte_offset_pointer ); SGLFW__check(__FILE__, __LINE__, name, att.index, "glVertexAttribPointer" );
0399 }
0400
0401
0402 inline void SGLFW_Program::enableVertexAttribArray_OfTransforms( const char* name ) const
0403 {
0404 assert( name );
0405
0406 SGLFW_Attrib att(name, SMesh::MATROW_SPEC );
0407
0408 att.index = getAttribLocation( name ); SGLFW__check(__FILE__, __LINE__,name, att.index, "getAttribLocation");
0409
0410 size_t qsize = att.stride/4 ;
0411 GLuint divisor = 1 ;
0412
0413
0414 const void* offset0 = (void*)(qsize*0) ;
0415 const void* offset1 = (void*)(qsize*1) ;
0416 const void* offset2 = (void*)(qsize*2) ;
0417 const void* offset3 = (void*)(qsize*3) ;
0418
0419 glEnableVertexAttribArray(att.index+0); SGLFW__check(__FILE__, __LINE__,name,att.index+0, "glEnableVertexAttribArray");
0420 glVertexAttribPointer(att.index+0, att.size, att.type, att.normalized, att.stride, offset0 ); SGLFW__check(__FILE__, __LINE__,name,att.index+0, "glVertexAttribPointer");
0421 glVertexAttribDivisor(att.index+0, divisor); SGLFW__check(__FILE__, __LINE__,name,att.index+0, "glVertexAttribDivisor");
0422
0423 glEnableVertexAttribArray(att.index+1); SGLFW__check(__FILE__, __LINE__,name,att.index+1, "glEnableVertexAttribArray");
0424 glVertexAttribPointer(att.index+1, att.size, att.type, att.normalized, att.stride, offset1 ); SGLFW__check(__FILE__, __LINE__,name,att.index+1, "glVertexAttribPointer");
0425 glVertexAttribDivisor(att.index+1, divisor); SGLFW__check(__FILE__, __LINE__,name,att.index+1, "glVertexAttribDivisor");
0426
0427 glEnableVertexAttribArray(att.index+2); SGLFW__check(__FILE__, __LINE__,name,att.index+2, "glEnableVertexAttribArray");
0428 glVertexAttribPointer(att.index+2, att.size, att.type, att.normalized, att.stride, offset2 ); SGLFW__check(__FILE__, __LINE__,name,att.index+2, "glVertexAttribPointer");
0429 glVertexAttribDivisor(att.index+2, divisor); SGLFW__check(__FILE__, __LINE__,name,att.index+2, "glVertexAttribDivisor");
0430
0431 glEnableVertexAttribArray(att.index+3); SGLFW__check(__FILE__, __LINE__,name,att.index+3, "glEnableVertexAttribArray");
0432 glVertexAttribPointer(att.index+3, att.size, att.type, att.normalized, att.stride, offset3 ); SGLFW__check(__FILE__, __LINE__,name,att.index+3, "glVertexAttribPointer");
0433 glVertexAttribDivisor(att.index+3, divisor); SGLFW__check(__FILE__, __LINE__,name,att.index+3, "glVertexAttribDivisor");
0434 }
0435
0436 inline void SGLFW_Program::Print_shader_info_log(unsigned id)
0437 {
0438 int max_length = 2048;
0439 int actual_length = 0;
0440 char log[2048];
0441
0442 glGetShaderInfoLog(id, max_length, &actual_length, log);
0443 SGLFW__check(__FILE__, __LINE__ );
0444
0445 printf("SGLFW_Program::Print_shader_info_log GL index %u:\n%s\n", id, log);
0446 assert(0);
0447 }
0448
0449