8 #include "ShaderProgramPool.hh"
9 #include <Base/Common/FileHandling.hh>
10 #include <Base/Math/Vector.hh>
11 #include <Utils/IOUtils.hh>
17 ShaderProgramPool::ShaderProgramPool()
19 all_program_linked_ =
false;
23 ShaderProgramPool::~ShaderProgramPool()
29 ShaderProgramPool::ClearAll()
31 all_program_linked_ =
false;
33 program_map_t::iterator program_iter = program_map_.begin();
35 for (; program_iter != program_map_.end(); program_iter++)
39 map<string, shader_map_t>::iterator shader_iter = shaders_.begin();
40 for (; shader_iter != shaders_.end(); shader_iter++)
43 shader_map_t::iterator iter = shader_map.begin();
44 for (; iter != shader_map.end(); iter++)
46 delete GetShader_(iter->second);
55 validitlyLinked_.clear();
65 ShaderProgramPool::AddShaderProgram(
const string& shader_program_name)
70 pair<program_map_t::iterator, bool> result = program_map_.insert(make_pair(
75 validitlyLinked_[shader_program_name] =
false;
80 GLF_THROW_EXCEPTION(
"program name :" << shader_program_name
81 <<
" already exists !" << endl);
83 all_program_linked_ =
false;
92 ShaderProgramPool::AddFragmentShader(
const string& shader_source,
93 const string& shader_name,
const string& shader_program_name)
95 AddShader_(GL_FRAGMENT_SHADER,shader_source, shader_name, shader_program_name);
96 all_program_linked_ =
false;
105 ShaderProgramPool::AddVertexShader(
const string& shader_source,
106 const string& shader_name,
const string& shader_program_name)
108 AddShader_(GL_VERTEX_SHADER,shader_source, shader_name, shader_program_name);
109 all_program_linked_ =
false;
113 ShaderProgramPool::AddFragmentShaderFromFile(
const string& path_to_shader,
114 const string& shader_name,
const string& shader_program_name)
116 string shader_source;
117 LoadShaderFromFile_(path_to_shader, shader_source);
118 AddFragmentShader(shader_source, shader_name, shader_program_name);
122 ShaderProgramPool::AddVertexShaderFromFile(
const string& path_to_shader,
123 const string& shader_name,
const string& shader_program_name)
125 string shader_source;
126 LoadShaderFromFile_(path_to_shader, shader_source);
127 AddVertexShader(shader_source, shader_name, shader_program_name);
134 ShaderProgramPool::RemoveShaderProgram(
const string& shader_program_name)
137 if (programP != NULL)
139 program_map_.erase(shader_program_name);
140 validitlyLinked_.erase(shader_program_name);
141 map<string, shader_map_t>::iterator shader_iter = shaders_.find(
142 shader_program_name);
143 if (shader_iter != shaders_.end())
146 shader_map_t::iterator iter = shader_map.begin();
147 for (; iter != shader_map.end(); iter++)
149 delete GetShader_(iter->second);
153 shaders_.erase(shader_iter);
165 ShaderProgramPool::GetShaderProgram(
const string& shader_program_name)
167 program_data_t* program_dataP = GetShaderProgramData_(shader_program_name);
168 if (program_dataP != NULL)
170 return program_dataP->first;
179 ShaderProgramPool::BindShaderProgram(
const string& shader_program_name)
182 if (programP != NULL)
189 ShaderProgramPool::IsLinked()
191 return all_program_linked_;
195 ShaderProgramPool::LinkAll()
197 if (!all_program_linked_)
199 program_map_t::iterator iter = program_map_.begin();
200 for (; iter != program_map_.end(); iter++)
204 if (!validitlyLinked_[iter->first])
206 (program_data.first)->Link();
207 validitlyLinked_[iter->first] =
true;
211 all_program_linked_ =
true;
216 ShaderProgramPool::GetShaderNames(
const string& shader_program_name, vector<
217 string>& shader_names)
219 shader_map_t* shaders_mapP = GetShadersMap_(shader_program_name);
220 if (shaders_mapP != NULL)
222 shader_map_t::iterator iter = shaders_mapP->begin();
223 for (; iter != shaders_mapP->end(); iter++)
225 shader_names.push_back(iter->first);
231 ShaderProgramPool::GetUniformType(
const string& shader_program_name,
232 const string& varName)
235 uniforms_map_t* uniforms_mapP = GetUniformMap_(shader_program_name);
236 if (uniforms_mapP == NULL)
238 GLF_THROW_EXCEPTION(
"program name :" << shader_program_name
239 <<
" does not exist !" << endl);
243 uniforms_map_t::iterator iter = uniforms_mapP->begin();
244 for (; iter != uniforms_mapP->end(); iter++)
246 list<string>& variable_list = iter->second;
247 list<string>::iterator var_iter = find(variable_list.begin(),
248 variable_list.end(), varName);
249 if (var_iter != variable_list.end())
259 template<
class StorageType>
261 ShaderProgramPool::SetUniformArray(
const std::string& shader_program_name,
262 const std::string& varName, StorageType value,
int arg_number)
264 if (all_program_linked_)
267 shader_program_name);
268 if (program_dataP == NULL)
270 GLF_THROW_EXCEPTION(
"program name :" << shader_program_name
271 <<
" does not exist !" << endl);
276 uniforms_map_t::iterator iter;
277 if (
typeid(StorageType) ==
typeid(
int*))
279 iter = uniforms_mapP->find(
"int_array");
283 GLF_THROW_EXCEPTION(
"SetUniform() is not implemented for type (" <<
typeid(StorageType).name() <<
")"<<endl);
286 if (iter != uniforms_mapP->end())
288 list<string>& uniforms = iter->second;
289 list<string>::iterator uniform_iter = find(uniforms.begin(),
290 uniforms.end(), varName);
291 if (uniform_iter != uniforms.end())
298 programP->
SetUniform(varName, arg_number, value);
303 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
304 <<
") exists in shader program : " << shader_program_name << endl);
309 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
310 <<
") exists in shader program : " << shader_program_name << endl);
316 GLF_THROW_EXCEPTION(
"all programs must be linked to set uniform variable, call LinkAll() first ! " << endl);
320 template<
class StorageType>
322 ShaderProgramPool::SetUniform(
const std::string& shader_program_name,
323 const std::string& varName, StorageType value)
326 if (all_program_linked_)
329 shader_program_name);
330 if (program_dataP == NULL)
332 GLF_THROW_EXCEPTION(
"program name :" << shader_program_name
333 <<
" does not exist !" << endl);
338 uniforms_map_t::iterator iter;
339 if (
typeid(StorageType) ==
typeid(
bool))
341 iter = uniforms_mapP->find(
"bool");
346 if (
typeid(StorageType) ==
typeid(
int))
348 iter = uniforms_mapP->find(
"int");
352 if (
typeid(StorageType) ==
typeid(
float)
353 ||
typeid(StorageType) ==
typeid(
double))
355 iter = uniforms_mapP->find(
"float");
361 ||
typeid(StorageType)
364 iter = uniforms_mapP->find(
"vec");
368 GLF_THROW_EXCEPTION(
"SetUniform() is not implemented for type (" <<
typeid(StorageType).name() <<
")"<<endl);
375 if (iter != uniforms_mapP->end())
377 list<string>& uniforms = iter->second;
378 list<string>::iterator uniform_iter = find(uniforms.begin(),
379 uniforms.end(), varName);
380 if (uniform_iter != uniforms.end())
387 iter = uniforms_mapP->find(
"sampler2D");
388 if (iter != uniforms_mapP->end())
390 list<string> & uniforms = iter->second;
391 list<string>::iterator uniform_iter = find(
392 uniforms.begin(), uniforms.end(), varName);
393 if (uniform_iter != uniforms.end())
400 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
401 <<
") exists in shader program : " << shader_program_name << endl);
406 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
407 <<
") exists in shader program : " << shader_program_name << endl);
413 if (
typeid(StorageType) ==
typeid(
int))
415 iter = uniforms_mapP->find(
"sampler2D");
416 if (iter != uniforms_mapP->end())
418 list<string>& uniforms = iter->second;
419 list<string>::iterator uniform_iter = find(
420 uniforms.begin(), uniforms.end(), varName);
421 if (uniform_iter != uniforms.end())
428 cout <<
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
429 <<
") exists in shader program : " << shader_program_name << endl;
430 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
431 <<
") exists in shader program : " << shader_program_name << endl);
436 GLF_THROW_EXCEPTION(
"no uniform variable with name (" << varName <<
") and type (" <<
typeid(StorageType).name()
437 <<
") exists in shader program : " << shader_program_name << endl);
442 GLF_THROW_EXCEPTION(
"no uniform variable with type (" <<
typeid(StorageType).name()
443 <<
") exists in shader program : " << shader_program_name << endl);
450 GLF_THROW_EXCEPTION(
"all programs must be linked to set uniform variable, call LinkAll() first ! " << endl);
457 ShaderProgramPool::GetShaderProgramData_(
const string& shader_program_name)
459 program_map_t::iterator iter = program_map_.find(shader_program_name);
460 if (iter != program_map_.end())
462 return &(iter->second);
471 ShaderProgramPool::AddShader_(GLenum type,
const string& shader_source,
472 const string& shader_name,
const string& shader_program_name)
474 program_data_t* program_dataP = GetShaderProgramData_(shader_program_name);
475 if (program_dataP == NULL)
477 GLF_THROW_EXCEPTION(
"program with name:" << shader_program_name
478 <<
" does not exist !" << endl);
482 glfShader* shaderP = GetShader_(shader_program_name, shader_name);
488 shaderP->
Create(type, shader_source);
496 shader_map_t& shader_map = (shaders_.insert(make_pair(
497 shader_program_name, shader_map_t())).first)->second;
498 shader_map[shader_name] = make_pair(shaderP, shader_source);
499 AddUniformDataFromSource_(*program_dataP, shader_source);
504 GLF_THROW_EXCEPTION(
"shader with name:" << shader_name
505 <<
" already exists !" << endl);
511 ShaderProgramPool::GetShadersMap_(
const std::string& shader_program_name)
513 map<string, shader_map_t>::iterator iter = shaders_.find(shader_program_name);
514 if (iter != shaders_.end())
516 return &(iter->second);
526 const std::string& shader_name)
528 shader_map_t::iterator iter = shader_map.find(shader_name);
529 if (iter != shader_map.end())
531 return &(iter->second);
540 ShaderProgramPool::GetUniformMap_(program_data_t& program_data)
542 return &((program_data).second);
546 ShaderProgramPool::GetUniformMap_(
const std::string& shader_program_name)
548 program_map_t::iterator iter = program_map_.find(shader_program_name);
549 if (iter != program_map_.end())
551 return GetUniformMap_(iter->second);
560 ShaderProgramPool::GetShaderSource_(shader_data_t& shader_data)
562 return &(shader_data.second);
566 ShaderProgramPool::GetShader_(shader_data_t& shader_data)
568 return shader_data.first;
572 ShaderProgramPool::GetShader_(
const string& shader_program_name,
573 const string& shader_name)
575 shader_map_t* shader_mapP = GetShadersMap_(shader_program_name);
576 if (shader_mapP != NULL)
578 shader_data_t* shader_dataP = GetShaderData_(*(shader_mapP), shader_name);
579 if (shader_dataP != NULL)
581 return GetShader_(*shader_dataP);
595 ShaderProgramPool::AddUniformDataFromSource_(program_data_t& program_data,
596 string shader_source)
599 shader_source = RemoveCommentariesFromSource_(shader_source);
601 string::size_type loc = shader_source.find(
"uniform ", 0);
603 while (loc != string::npos)
605 string::size_type pos = shader_source.find(
';', loc);
606 if (pos == string::npos)
608 IOUtils::PrintWithLineNumbers(shader_source);
609 BIASERR(
"; missing " <<endl);
613 string::size_type length = pos - loc;
614 char* data =
new char[length + 1];
615 shader_source.copy(data, length, loc);
621 for (
int i = length; i >= 0; i--)
623 if (data[i] ==
'[' || data[i] ==
']')
629 vector<string> str_v(3);
630 unsigned int index = 0;
632 tokenP = strtok(data,
" = [");
633 while (tokenP != NULL)
635 if (index >= str_v.size())
641 str_v[index] = string(tokenP);
643 tokenP = strtok(NULL,
" = [");
647 if (index < str_v.size() - 1)
649 IOUtils::PrintWithLineNumbers(shader_source);
650 BIASERR(
"error parsing uniforms !"<<endl);
658 AddUniformVariable_(program_data, str_v[1] +
"_array", str_v[2]);
663 AddUniformVariable_(program_data, str_v[1], str_v[2]);
665 loc = shader_source.find(
"uniform", pos);
670 ShaderProgramPool::AddUniformVariable_(program_data_t& program_data,
671 const string& type,
const string& name)
673 uniforms_map_t& uniform_map = *(GetUniformMap_(program_data));
675 string::size_type loc = type.find(
"vec");
676 if (loc != string::npos)
678 uniform_map[string(
"vec")].push_back(name);
682 uniform_map[type].push_back(name);
688 ShaderProgramPool::LoadShaderFromFile_(
const string& shader_path,
689 string& shader_source)
691 ifstream ifs(shader_path.c_str());
694 GLF_THROW_EXCEPTION(
"Failed to load shader source file: " << shader_path);
701 shader_source += line +
"\r\n";
706 ShaderProgramPool::GetShaderProgram_(
709 return program_data.first;
713 ShaderProgramPool::RemoveCommentariesFromSource_(
const string& source)
715 string copyString = source;
716 string::size_type pos = 0;
717 while (pos != string::npos)
719 pos = copyString.find(
"//");
720 if (pos != string::npos)
722 string::size_type new_pos = copyString.find(
'\n',pos);
723 copyString.erase(pos, new_pos - pos + 1);
731 template void BIASOpenGLFramework_EXPORT
732 ShaderProgramPool::SetUniform<int>(
const string& shader_program_name,
733 const string& varName,
int value);
734 template void BIASOpenGLFramework_EXPORT
735 ShaderProgramPool::SetUniform<bool>(
const string& shader_program_name,
736 const string& varName,
bool value);
737 template void BIASOpenGLFramework_EXPORT
738 ShaderProgramPool::SetUniform<float>(
const string& shader_program_name,
739 const string& varName,
float value);
740 template void BIASOpenGLFramework_EXPORT
741 ShaderProgramPool::SetUniform<double>(
const string& shader_program_name,
742 const string& varName,
double value);
743 template void BIASOpenGLFramework_EXPORT
744 ShaderProgramPool::SetUniform<Vector<float> >(
745 const string& shader_program_name,
const string& varName,
749 template void BIASOpenGLFramework_EXPORT
750 ShaderProgramPool::SetUniformArray<int*>(
const string& shader_program_name,
751 const string& varName,
int* value,
int arg_number);
void Create()
Creates the shader program.
void SetUniform(const std::string &varName, float value)
void AttachShader(const glfShader &shader)
Attaches a shader to the program.
std::map< std::string, std::list< std::string > > uniforms_map_t
void Create(GLenum type)
Creates the shader without the GLSL source code, use other Create() methods to upload source afterwar...
std::pair< glfShaderProgram *, uniforms_map_t > program_data_t
void Bind() const
Binds the shader program.
A shader program composed of several shaders.
A GLSL vertex shader or fragment shader, which must be linked in a shader program.
std::pair< glfShader *, std::string > shader_data_t
std::map< std::string, shader_data_t > shader_map_t