Support for static shaders in ShaderManager

pull/3/head
Hleb Valoshka 2019-06-17 18:56:47 +03:00
parent b09b48b1ab
commit 9745b125f3
4 changed files with 199 additions and 18 deletions

View File

@ -125,6 +125,24 @@ Vec4ShaderParameter::operator=(const Eigen::Vector4f& v)
}
IntegerShaderParameter::IntegerShaderParameter() :
slot(-1)
{
}
IntegerShaderParameter::IntegerShaderParameter(GLuint obj, const char* name)
{
slot = glGetUniformLocation(obj, name);
}
IntegerShaderParameter&
IntegerShaderParameter::operator=(int i)
{
if (slot != -1)
glUniform1i(slot, i);
return *this;
}
//************* GLProgram **************
GLProgram::GLProgram(GLuint _id) :

View File

@ -124,6 +124,18 @@ class Vec4ShaderParameter
};
class IntegerShaderParameter
{
public:
IntegerShaderParameter();
IntegerShaderParameter(GLuint obj, const char* name);
IntegerShaderParameter& operator=(int);
private:
int slot;
};
class GLShaderLoader
{

View File

@ -19,6 +19,7 @@
#include <fmt/printf.h>
#include <cassert>
#include <Eigen/Geometry>
#include <sys/stat.h>
using namespace Eigen;
using namespace std;
@ -290,19 +291,22 @@ ShaderManager::ShaderManager()
ShaderManager::~ShaderManager()
{
for(const auto& shader : shaders)
{
for(const auto& shader : dynamicShaders)
delete shader.second;
}
shaders.clear();
dynamicShaders.clear();
for(const auto& shader : staticShaders)
delete shader.second;
staticShaders.clear();
}
CelestiaGLProgram*
ShaderManager::getShader(const ShaderProperties& props)
{
map<ShaderProperties, CelestiaGLProgram*>::iterator iter = shaders.find(props);
if (iter != shaders.end())
auto iter = dynamicShaders.find(props);
if (iter != dynamicShaders.end())
{
// Shader already exists
return iter->second;
@ -311,12 +315,88 @@ ShaderManager::getShader(const ShaderProperties& props)
{
// Create a new shader and add it to the table of created shaders
CelestiaGLProgram* prog = buildProgram(props);
shaders[props] = prog;
dynamicShaders[props] = prog;
return prog;
}
}
CelestiaGLProgram*
ShaderManager::getShader(const string& name, const string& vs, const string& fs)
{
auto iter = staticShaders.find(name);
if (iter != staticShaders.end())
{
// Shader already exists
return iter->second;
}
// Create a new shader and add it to the table of created shaders
CelestiaGLProgram* prog = buildProgram(vs, fs);
staticShaders[name] = prog;
return prog;
}
#ifndef _WIN32
constexpr const char fsDelimeter = '/';
#else
constexpr const char fsDelimeter = '\\';
#endif
CelestiaGLProgram*
ShaderManager::getShader(const string& name)
{
auto iter = staticShaders.find(name);
if (iter != staticShaders.end())
{
// Shader already exists
return iter->second;
}
auto vsName = fmt::sprintf("shaders%c%s_vert.glsl", fsDelimeter, name);
auto fsName = fmt::sprintf("shaders%c%s_frag.glsl", fsDelimeter, name);
struct stat s;
if (stat(vsName.c_str(), &s) == -1)
{
fmt::fprintf(cerr, "Failed to stat %s\n", vsName);
return getShader(name, errorVertexShaderSource, errorFragmentShaderSource);
}
auto vsSize = s.st_size;
if (stat(fsName.c_str(), &s) == -1)
{
fmt::fprintf(cerr, "Failed to stat %s\n", fsName);
return getShader(name, errorVertexShaderSource, errorFragmentShaderSource);
}
auto fsSize = s.st_size;
ifstream vsf(vsName);
if (!vsf.good())
{
fmt::fprintf(cerr, "Failed to open %s\n", vsName);
return getShader(name, errorVertexShaderSource, errorFragmentShaderSource);
}
ifstream fsf(fsName);
if (!fsf.good())
{
fmt::fprintf(cerr, "Failed to open %s\n", fsName);
return getShader(name, errorVertexShaderSource, errorFragmentShaderSource);
}
string vs(vsSize, '\0'), fs(fsSize, '\0');
vsf.read(&vs[0], vsSize);
fsf.read(&fs[0], fsSize);
// Create a new shader and add it to the table of created shaders
CelestiaGLProgram* prog = buildProgram(vs, fs);
staticShaders[name] = prog;
return prog;
}
static string
LightProperty(unsigned int i, const char* property)
@ -3095,6 +3175,51 @@ ShaderManager::buildProgram(const ShaderProperties& props)
return new CelestiaGLProgram(*prog, props);
}
CelestiaGLProgram*
ShaderManager::buildProgram(const std::string& vs, const std::string& fs)
{
GLProgram* prog = nullptr;
GLShaderStatus status;
DumpVSSource(vs);
DumpFSSource(fs);
status = GLShaderLoader::CreateProgram(vs, fs, &prog);
if (status == ShaderStatus_OK)
{
// Tangents always in attribute 6 (should be a constant
// someplace)
glBindAttribLocation(prog->getID(), 6, "tangent");
// Point size is always in attribute 7
glBindAttribLocation(prog->getID(), 7, "pointSize");
status = prog->link();
}
if (status != ShaderStatus_OK)
{
// If the shader creation failed for some reason, substitute the
// error shader.
status = GLShaderLoader::CreateProgram(errorVertexShaderSource,
errorFragmentShaderSource,
&prog);
if (status != ShaderStatus_OK)
{
if (g_shaderLogFile != nullptr)
*g_shaderLogFile << "Failed to create error shader!\n";
}
else
{
status = prog->link();
}
}
if (prog == nullptr)
return nullptr;
return new CelestiaGLProgram(*prog);
}
CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program,
const ShaderProperties& _props) :
@ -3106,6 +3231,11 @@ CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program,
};
CelestiaGLProgram::CelestiaGLProgram(GLProgram& _program) :
program(&_program)
{
}
CelestiaGLProgram::~CelestiaGLProgram()
{
delete program;
@ -3119,6 +3249,20 @@ CelestiaGLProgram::floatParam(const string& paramName)
}
IntegerShaderParameter
CelestiaGLProgram::intParam(const string& paramName)
{
return IntegerShaderParameter(program->getID(), paramName.c_str());
}
IntegerShaderParameter
CelestiaGLProgram::samplerParam(const string& paramName)
{
return IntegerShaderParameter(program->getID(), paramName.c_str());
}
Vec3ShaderParameter
CelestiaGLProgram::vec3Param(const string& paramName)
{

View File

@ -153,6 +153,7 @@ struct CelestiaGLProgramShadow
class CelestiaGLProgram
{
public:
CelestiaGLProgram(GLProgram& _program);
CelestiaGLProgram(GLProgram& _program, const ShaderProperties&);
~CelestiaGLProgram();
@ -173,12 +174,12 @@ class CelestiaGLProgram
float atmPlanetRadius,
float objRadius);
enum
{
VertexCoordAttributeIndex = 0,
TangentAttributeIndex = 6,
PointSizeAttributeIndex = 7,
};
enum
{
VertexCoordAttributeIndex = 0,
TangentAttributeIndex = 6,
PointSizeAttributeIndex = 7,
};
public:
CelestiaGLProgramLight lights[MaxShaderLights];
@ -249,14 +250,16 @@ class CelestiaGLProgram
CelestiaGLProgramShadow shadows[MaxShaderLights][MaxShaderEclipseShadows];
FloatShaderParameter floatParam(const std::string&);
IntegerShaderParameter intParam(const std::string&);
IntegerShaderParameter samplerParam(const std::string&);
Vec3ShaderParameter vec3Param(const std::string&);
Vec4ShaderParameter vec4Param(const std::string&);
private:
void initParameters();
void initSamplers();
FloatShaderParameter floatParam(const std::string&);
Vec3ShaderParameter vec3Param(const std::string&);
Vec4ShaderParameter vec4Param(const std::string&);
GLProgram* program;
const ShaderProperties props;
};
@ -269,9 +272,12 @@ class ShaderManager
~ShaderManager();
CelestiaGLProgram* getShader(const ShaderProperties&);
CelestiaGLProgram* getShader(const std::string&);
CelestiaGLProgram* getShader(const std::string&, const std::string&, const std::string&);
private:
CelestiaGLProgram* buildProgram(const ShaderProperties&);
CelestiaGLProgram* buildProgram(const std::string&, const std::string&);
GLVertexShader* buildVertexShader(const ShaderProperties&);
GLFragmentShader* buildFragmentShader(const ShaderProperties&);
@ -291,7 +297,8 @@ class ShaderManager
GLVertexShader* buildStaticVertexShader(const ShaderProperties&);
GLFragmentShader* buildStaticFragmentShader(const ShaderProperties&);
std::map<ShaderProperties, CelestiaGLProgram*> shaders;
std::map<ShaderProperties, CelestiaGLProgram*> dynamicShaders;
std::map<std::string, CelestiaGLProgram*> staticShaders;
};
#endif // _CELENGINE_SHADERMANAGER_H_