bluecore/engine/ShaderManager.cpp

323 lines
6.8 KiB
C++

#include "ShaderManager.h"
#include "Utilities/Log.h"
#include "Utilities/CfgParser.h"
// library includes
#include "physfs.h"
// system includes
#include <iostream>
#include <vector>
using namespace std;
namespace BlueCore
{
ShaderManager::ShaderManager(RenderWindow* renderwindow) :
_usingShaders(true), _RenderWindow(renderwindow)
{
glewInit();
if (GLEW_ARB_fragment_shader == false)
_usingShaders = false;
_RenderWindow->WindowCloseSignal.connect(this,
&ShaderManager::WindowCloseSlot);
clog << ">>> ShaderManager constructed ..."<< endline;
if (_usingShaders)
clog << " using shaders"<< endline;
else
clog << " shaders not supported!"<< endlog;
}
ShaderManager::~ShaderManager()
{
clog << ">>> ShaderManager destructed ..."<< endlog;
}
void ShaderManager::shutdown()
{
clog << ">>> ShaderManager shutting down ..."<< endlog;
ShaderProgramMap::iterator prog_iter;
for (prog_iter = shader_programs.begin(); prog_iter!= shader_programs.end(); prog_iter++)
{
glDeleteObjectARB(prog_iter->second);
}
shader_programs.clear();
VertexShaderMap::iterator vert_iter;
for (vert_iter = vertex_shader.begin(); vert_iter != vertex_shader.end(); vert_iter++)
{
glDeleteObjectARB(vert_iter->second);
}
vertex_shader.clear();
FragmentShaderMap::iterator frag_iter;
for (frag_iter = fragment_shader.begin(); frag_iter!= fragment_shader.end(); frag_iter++)
{
glDeleteObjectARB(frag_iter->second);
}
fragment_shader.clear();
}
void ShaderManager::WindowCloseSlot()
{
shutdown();
}
bool ShaderManager::usingShaders()
{
return _usingShaders;
}
void printInfoLog(GLhandleARB obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
&infologLength);
if (infologLength > 1)
{
infoLog = new char[infologLength+1];
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
clog << " "<< infoLog << endline;
delete [] infoLog;
}
}
VertexShader ShaderManager::loadVertexShader(const string &name)
{
if ( !_usingShaders)
return 0;
// check if this mesh is already loaded
VertexShaderMap::const_iterator result;
result = vertex_shader.find(name);
if (result != vertex_shader.end() )
{
return result->second;
}
//string filename = name + ".vert";
PHYSFS_file *file = PHYSFS_openRead(name.c_str() );
if ( !file)
{
clog << "!!! VertexShader '"<< name << "' not found"<< endline;
return 0;
}
char *buffer = new char[ PHYSFS_fileLength ( file ) ];
PHYSFS_read(file, buffer, 1, PHYSFS_fileLength(file) );
buffer[ PHYSFS_fileLength ( file ) - 1] = 0;
PHYSFS_close(file);
VertexShader shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
glShaderSourceARB(shader, 1, ( const GLcharARB** ) &buffer, NULL);
delete [] buffer;
glCompileShaderARB(shader);
vertex_shader[name] = shader;
clog << ">>> VertexShader '"<< name << "' loaded"<< endline;
return shader;
}
FragmentShader ShaderManager::loadFragmentShader(const string &name)
{
if ( !_usingShaders)
return 0;
// check if this mesh is already loaded
FragmentShaderMap::const_iterator result;
result = fragment_shader.find(name);
if (result != fragment_shader.end() )
{
return result->second;
}
//string filename = name + ".frag";
PHYSFS_file *file = PHYSFS_openRead(name.c_str() );
if ( !file)
{
clog << "!!! FragmentShader '"<< name << "' not found"<< endline;
return 0;
}
char *buffer = new char[ PHYSFS_fileLength ( file ) ];
PHYSFS_read(file, buffer, 1, PHYSFS_fileLength(file) );
buffer[ PHYSFS_fileLength ( file ) - 1] = 0;
PHYSFS_close(file);
FragmentShader shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(shader, 1, ( const GLcharARB** ) &buffer, NULL);
delete [] buffer;
glCompileShaderARB(shader);
printInfoLog(shader);
fragment_shader[name] = shader;
clog << ">>> FragmentShader '"<< name << "' loaded"<< endline;
return shader;
}
ShaderProgram ShaderManager::loadShaderProgram(const std::string &name)
{
if ( !_usingShaders)
return 0;
if (name.empty() )
return 0;
// check if this mesh is already loaded
ShaderProgramMap::const_iterator result;
result = shader_programs.find(name);
if (result != shader_programs.end() )
{
return result->second;
}
string filename = name + ".prog";
PHYSFS_file *file = PHYSFS_openRead(filename.c_str() );
if ( !file)
{
clog << "!!! ShaderProgramm '"<< name << "' not found"<< endline;
return 0;
}
unsigned int length = PHYSFS_fileLength(file);
char *buffer = new char[length];
PHYSFS_read(file, buffer, 1, length);
PHYSFS_close(file);
CfgParser cfg;
cfg.parse(buffer, length);
delete [] buffer;
ShaderProgram program = glCreateProgramObjectARB();
std::vector<std::string> vertex_shaders;
if (cfg.getStrings("vertex_shaders", vertex_shaders) )
{
for (unsigned int i = 0; i < vertex_shaders.size(); i++)
{
VertexShader shader = loadVertexShader(vertex_shaders[i]);
if (shader != 0)
glAttachObjectARB(program, shader);
}
}
std::vector<std::string> fragment_shaders;
if (cfg.getStrings("fragment_shaders", fragment_shaders) )
{
for (unsigned int i = 0; i < fragment_shaders.size(); i++)
{
FragmentShader shader = loadFragmentShader(fragment_shaders[i]);
if (shader != 0)
glAttachObjectARB(program, shader);
}
}
glLinkProgramARB(program);
printInfoLog(program);
shader_programs[name] = program;
clog << ">>> ShaderProgramm '"<< name << "' loaded"<< endline;
return program;
}
void ShaderManager::useShaderProgram(ShaderProgram shader_program)
{
if ( !_usingShaders)
return;
glUseProgramObjectARB(shader_program);
}
void ShaderManager::useTexture(ShaderProgram shader_program,
unsigned int texture, const std::string &name)
{
if ( !_usingShaders)
return;
GLint location = glGetUniformLocationARB(shader_program, name.c_str() );
//if( location > 0 )
glUniform1iARB(location, texture);
}
/*
void ShaderManager::useTangentBuffer (
ShaderProgram shader_program,
TangentBuffer *tangent_buffer,
const std::string &name )
{
if ( !_usingShaders || !tangent_buffer )
return;
GLuint location = glGetAttribLocationARB ( shader_program, name.c_str() );
glEnableVertexAttribArrayARB ( location );
tangent_buffer->bind();
glVertexAttribPointerARB ( location, 3, GL_FLOAT, 0, 0, 0 );
}
void ShaderManager::disableTangentBuffer (
ShaderProgram shader_program,
const std::string &name )
{
if ( !_usingShaders )
return;
GLuint location = glGetAttribLocationARB ( shader_program, name.c_str() );
glDisableVertexAttribArrayARB ( location );
}
*/
}