405 lines
12 KiB
C++
405 lines
12 KiB
C++
#include "include/ShaderManager/ShaderManager.h"
|
|
|
|
#include "include/Utils/Utils.h"
|
|
#include "include/Engine.h"
|
|
|
|
namespace SE
|
|
{
|
|
|
|
//===================================================
|
|
//============== SHADER RESOURCE ====================
|
|
//===================================================
|
|
|
|
|
|
|
|
TShaderResource::TShaderResource()
|
|
: ShaderProgram(0)
|
|
{
|
|
}
|
|
|
|
TShaderResource::~TShaderResource()
|
|
{
|
|
|
|
*Console<<"ResourceManager::ShaderManager::Shader deleting";
|
|
FreeShader();
|
|
|
|
}
|
|
|
|
bool TShaderResource::CompileShader(boost::shared_array<char> vertexCode, boost::shared_array<char> fragmentCode)
|
|
{
|
|
|
|
FreeShader();
|
|
|
|
const int CONST_INFOLOG_LENGTH = 256;
|
|
|
|
char infoLog[CONST_INFOLOG_LENGTH];
|
|
int infoLogLength;
|
|
|
|
int vertexShaderCompiled;
|
|
int fragmentShaderCompiled;
|
|
int programLinked;
|
|
|
|
cardinal vertexShader;
|
|
cardinal fragmentShader;
|
|
|
|
int vertexCodeLength = strlen(vertexCode.get());
|
|
int fragmentCodeLength = strlen(fragmentCode.get());
|
|
|
|
const char* vc = &vertexCode[0];
|
|
const char* fc = &fragmentCode[0];
|
|
|
|
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
|
|
|
|
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
|
|
|
|
glCompileShader(vertexShader);
|
|
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
|
|
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
|
*Console<<"ResourceManager::ShaderManager::Shader "+std::string(infoLog);
|
|
|
|
glCompileShader(fragmentShader);
|
|
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
|
|
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
|
*Console<<"ResourceManager::ShaderManager::Shader " + std::string(infoLog);
|
|
|
|
if (!vertexShaderCompiled || !fragmentShaderCompiled)
|
|
return false;
|
|
|
|
ShaderProgram = glCreateProgram();
|
|
*Console<<"Shader program is - " + tostr(ShaderProgram);
|
|
glAttachShader(ShaderProgram, vertexShader);
|
|
glAttachShader(ShaderProgram, fragmentShader);
|
|
|
|
glLinkProgram(ShaderProgram);
|
|
|
|
glDeleteShader(vertexShader);
|
|
glDeleteShader(fragmentShader);
|
|
|
|
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &programLinked);
|
|
glGetProgramInfoLog(ShaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
|
|
|
*Console<<"ResourceManager::ShaderManager::Shader "+std::string(infoLog);
|
|
|
|
if (!programLinked)
|
|
{
|
|
ShaderProgram = 0;
|
|
return false;
|
|
}
|
|
|
|
|
|
int dummySize; //Dummy
|
|
int dummyLen; //Dummy
|
|
cardinal dummyType; //Dummy
|
|
|
|
//================= Parsing all uniforms ================
|
|
|
|
int activeUniforms;
|
|
|
|
const int CONST_UNIFORM_NAME_LENGTH = 256;
|
|
char uniformName[CONST_UNIFORM_NAME_LENGTH];
|
|
|
|
glGetProgramiv(ShaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
|
|
|
|
for (int i = 0; i < activeUniforms; i++)
|
|
{
|
|
glGetActiveUniform(ShaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize, &dummyType, uniformName);
|
|
UniformList[uniformName] = glGetUniformLocation(ShaderProgram, uniformName);
|
|
}
|
|
|
|
//================= Parsing all attributes ================
|
|
int activeAttribs;
|
|
|
|
const int CONST_ATTRIB_NAME_LENGTH = 256;
|
|
char attribName[CONST_ATTRIB_NAME_LENGTH];
|
|
|
|
glGetProgramiv(ShaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
|
|
|
|
for (int i = 0; i < activeAttribs; i++)
|
|
{
|
|
glGetActiveAttrib(ShaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize, &dummyType, attribName);
|
|
AttribList[attribName] = glGetAttribLocation(ShaderProgram, attribName);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void TShaderResource::FreeShader()
|
|
{
|
|
|
|
if (ShaderProgram != 0)
|
|
{
|
|
#ifdef TARGET_ANDROID
|
|
if (glIsProgram(ShaderProgram))
|
|
{
|
|
glDeleteProgram(ShaderProgram);
|
|
}
|
|
#else
|
|
glDeleteProgram(ShaderProgram);
|
|
#endif
|
|
ShaderProgram = 0;
|
|
}
|
|
|
|
UniformList.clear();
|
|
AttribList.clear();
|
|
}
|
|
|
|
int TShaderResource::GetAttribIndex(const std::string& attribName)
|
|
{
|
|
if (AttribList.count(attribName) > 0)
|
|
return AttribList[attribName];
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
int TShaderResource::GetUniformIndex(const std::string& uniformName)
|
|
{
|
|
if (UniformList.count(uniformName) > 0)
|
|
return UniformList[uniformName];
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
//===================================================
|
|
//=============== SHADER MANAGER ====================
|
|
//===================================================
|
|
|
|
|
|
TShaderManager::~TShaderManager()
|
|
{
|
|
Clear();
|
|
*Console<<"ResourceManager::ShaderManager deleting";
|
|
}
|
|
|
|
std::shared_ptr<TShaderResource> TShaderManager::GetCurrentShader()
|
|
{
|
|
if (ShaderNameStack.size() == 0)
|
|
{
|
|
throw ErrorToLog("GetCurrentShader: Shader is not selected!");
|
|
}
|
|
|
|
return ShaderList[ShaderNameStack.top()];
|
|
}
|
|
|
|
void TShaderManager::Serialize(boost::property_tree::ptree& propertyTree)
|
|
{
|
|
|
|
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, propertyTree.get_child("Shaders"))
|
|
{
|
|
std::string shaderName = v.second.get<std::string>("Name");
|
|
std::string vertexFileName = v.second.get<std::string>("VertexFileName");
|
|
std::string fragmentFileName = v.second.get<std::string>("FragmentFileName");
|
|
|
|
AddShader(shaderName, vertexFileName, fragmentFileName);
|
|
|
|
}
|
|
}
|
|
|
|
bool TShaderManager::AddShader(const std::string& shaderName, const std::string& vertexFileName, const std::string& fragmentFileName)
|
|
{
|
|
|
|
std::string pathToResources = ResourceManager->PathToResources;
|
|
|
|
if (ShaderList.count(shaderName) > 0)
|
|
{
|
|
*Console<<"ResourceManager::ShaderManager ERROR shader already exists: "+shaderName;
|
|
return false;
|
|
}
|
|
|
|
*Console<<"Prepare to add shader "+shaderName;
|
|
cardinal fSize;
|
|
boost::shared_array<char> fPointer;
|
|
boost::shared_array<char> vertexCode;
|
|
boost::shared_array<char> fragmentCode;
|
|
|
|
fPointer = CreateMemFromFile<char>(pathToResources + vertexFileName, fSize);
|
|
|
|
vertexCode = boost::shared_array<char>(new char [fSize + 1]);
|
|
|
|
memcpy(vertexCode.get(), fPointer.get(), fSize);
|
|
|
|
vertexCode[fSize] = 0;
|
|
|
|
fPointer = CreateMemFromFile<char>(pathToResources + fragmentFileName, fSize);
|
|
|
|
fragmentCode = boost::shared_array<char>(new char [fSize + 1]);
|
|
|
|
memcpy(fragmentCode.get(), fPointer.get(), fSize);
|
|
|
|
fragmentCode[fSize] = 0;
|
|
|
|
std::shared_ptr<TShaderResource> shaderResource(new TShaderResource);
|
|
|
|
ShaderList[shaderName] = shaderResource;
|
|
|
|
if (!ShaderList[shaderName]->CompileShader(vertexCode, fragmentCode))
|
|
{
|
|
*Console<<"ResourceManager::ShaderManager ERROR shader could not be compiled or linked: "+shaderName;
|
|
return false;
|
|
}
|
|
|
|
*Console<<"ResourceManager::ShaderManager shader loaded: "+shaderName;
|
|
|
|
return true;
|
|
}
|
|
|
|
void TShaderManager::Clear()
|
|
{
|
|
glUseProgram(0);
|
|
ShaderList.clear();
|
|
*Console<<"ResourceManager::ShaderManager cleared";
|
|
}
|
|
|
|
|
|
void TShaderManager::PushShader(const std::string& shaderName)
|
|
{
|
|
|
|
if (ShaderList.count(shaderName) == 0)
|
|
throw ErrorShaderNotExists(shaderName);
|
|
|
|
if (ShaderNameStack.size() >= CONST_MAX_STACK_SIZE)
|
|
throw ErrorShaderStackOverflow();
|
|
|
|
|
|
if (ShaderNameStack.size() == 0 || ShaderNameStack.top() != shaderName)
|
|
{
|
|
glUseProgram(ShaderList[shaderName]->ShaderProgram);
|
|
}
|
|
|
|
ShaderNameStack.push(shaderName);
|
|
}
|
|
|
|
|
|
void TShaderManager::PopShader()
|
|
{
|
|
if (ShaderNameStack.size() <= 1)
|
|
{
|
|
throw ErrorToLog("Shader stack underflow!!");
|
|
}
|
|
std::string oldShaderName = ShaderNameStack.top();
|
|
|
|
ShaderNameStack.pop();
|
|
std::string shaderName = ShaderNameStack.top();
|
|
if (oldShaderName != shaderName)
|
|
{
|
|
glUseProgram(ShaderList[shaderName]->ShaderProgram);
|
|
}
|
|
}
|
|
|
|
//========================================================
|
|
//======================== Utilities =====================
|
|
//========================================================
|
|
|
|
void RenderUniform1f(const std::string& uniformName, const float value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniform1fv(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],1,&value);
|
|
}
|
|
|
|
void RenderUniform3fv(const std::string& uniformName, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniform3fv(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],1,value);
|
|
}
|
|
|
|
void RenderUniform4fv(const std::string& uniformName, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniform4fv(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],1,value);
|
|
}
|
|
|
|
|
|
void RenderUniformMatrix3fv(const std::string& uniformName,bool transpose, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniformMatrix3fv(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],1,transpose,value);
|
|
|
|
}
|
|
|
|
void RenderUniformMatrix4fv(const std::string& uniformName,bool transpose, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniformMatrix4fv(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],1,transpose,value);
|
|
|
|
}
|
|
|
|
|
|
void RenderUniform1i(const std::string& uniformName, const int value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->UniformList.count(uniformName) > 0)
|
|
glUniform1i(ResourceManager->ShaderManager.GetCurrentShader()->UniformList[uniformName],value);
|
|
}
|
|
|
|
void VertexAttrib2fv(const std::string& attribName, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glVertexAttrib2fv(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName], value);
|
|
}
|
|
|
|
void VertexAttrib3fv(const std::string& attribName, const float* value)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glVertexAttrib3fv(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName], value);
|
|
}
|
|
|
|
void VertexAttribPointer2fv(const std::string& attribName,int stride, const char* pointer)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glVertexAttribPointer(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName], 2, GL_FLOAT, GL_FALSE, stride, pointer);
|
|
}
|
|
|
|
void VertexAttribPointer3fv(const std::string& attribName,int stride, const char* pointer)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glVertexAttribPointer(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName], 3, GL_FLOAT, GL_FALSE, stride, pointer);
|
|
}
|
|
|
|
void EnableVertexAttribArray(const std::string& attribName)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glEnableVertexAttribArray(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName]);
|
|
}
|
|
|
|
void DisableVertexAttribArray(const std::string& attribName)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
glDisableVertexAttribArray(ResourceManager->ShaderManager.GetCurrentShader()->AttribList[attribName]);
|
|
}
|
|
|
|
|
|
#ifdef TARGET_WIN32
|
|
void RefreshAttribBuffer2fv(const std::string& attribName, std::map<std::string, std::vector<vec2> >& vec2CoordArr)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
if (vec2CoordArr[attribName].size() > 0)
|
|
glBufferData(GL_ARRAY_BUFFER, vec2CoordArr[attribName].size()*8, &(*vec2CoordArr[attribName].begin()), GL_STATIC_DRAW);
|
|
|
|
}
|
|
|
|
void RefreshAttribBuffer3fv(const std::string& attribName, std::map<std::string, std::vector<vec3> >& vec3CoordArr)
|
|
{
|
|
if (ResourceManager != NULL)
|
|
if (ResourceManager->ShaderManager.GetCurrentShader()->AttribList.count(attribName) > 0)
|
|
if (vec3CoordArr[attribName].size() > 0)
|
|
glBufferData(GL_ARRAY_BUFFER, vec3CoordArr[attribName].size()*12, &(*vec3CoordArr[attribName].begin()), GL_STATIC_DRAW);
|
|
}
|
|
#endif
|
|
|
|
} //namespace SE
|