File RenderShader.cpp
File List > render > shaders > RenderShader.cpp
Go to the documentation of this file
#include "RenderShader.h"
#include "operator.h"
#include "structs.h"
#include "macros.h"
void RenderShader::CreatShader(const std::string& verShader, const std::string& fragShader) {
program_id = glCreateProgram();
shader_data[VERTEX_SHADER].sh_ID = CompileShaderCode(VERTEX_SHADER, verShader);
shader_data[FRAGMENT_SHADER].sh_ID = CompileShaderCode(FRAGMENT_SHADER, fragShader);
glAttachShader(program_id, shader_data[VERTEX_SHADER].sh_ID);
glAttachShader(program_id, shader_data[FRAGMENT_SHADER].sh_ID);
glLinkProgram(program_id);
glValidateProgram(program_id);
//glDeleteShader(vs_id);
//glDeleteShader(fs_id);
//glDeleteProgram(program_id);
}
RenderShader::RenderShader(const std::string& vert, const std::string& frag)
{
shader_data[VERTEX_SHADER].sh_name = vert;
shader_data[FRAGMENT_SHADER].sh_name = frag == "" ? vert : frag;
shader_data[VERTEX_SHADER].sh_struct = ShaderStruct();
shader_data[FRAGMENT_SHADER].sh_struct = ShaderStruct();
shader_data[VERTEX_SHADER].sh_type = VERTEX_SHADER;
shader_data[FRAGMENT_SHADER].sh_type = FRAGMENT_SHADER;
ParseShaderFile(shader_data[VERTEX_SHADER].sh_name, VERTEX_SHADER);
ParseShaderFile(shader_data[FRAGMENT_SHADER].sh_name, FRAGMENT_SHADER);
GenerateShader(VERTEX_SHADER);
GenerateShader(FRAGMENT_SHADER);
CreatShader(shader_data[VERTEX_SHADER].sh_code, shader_data[FRAGMENT_SHADER].sh_code);
}
RenderShader::RenderShader()
{
}
RenderShader::~RenderShader()
{
}
void RenderShader::ParseShaderFile(std::string _name, ShaderType _type) {
Timer timer("ParseShader");
shader_data[_type].sh_struct->is_struct_changed = false;
if (_name.find(Shaders::folder_root) == std::string::npos) {
// Check if the name already has a file extension
if (Shaders::ParseFileEXT(_name) == NONE_SHADER) {
// No extension found, add the appropriate one
_name = Shaders::folder_root + _name + Shaders::file_type[_type];
}
else {
// Extension already present, just add folder_root
_name = Shaders::folder_root + _name;
}
}
std::ifstream Stream(_name);
ParseShaderStream(Stream, _type);
std::cout << "shaders are loaded up successfully!" << std::endl;
//m_shaders = { shaders[0].str(),shaders[1].str() };
}
void RenderShader::ParseShaderCode(const std::string& _code, ShaderType _type)
{
ShaderUnit* shader = GetShaderUnit(_type);
shader->sh_struct->Reset();
_LINK_LOC = {};
if (!_code.empty())
shader->sh_code = _code;
std::stringstream Stream(shader->sh_code);
ParseShaderStream(Stream, _type);
}
GLuint RenderShader::CompileShader(ShaderType tar)
{
ShaderUnit* shader = GetShaderUnit(tar);
GLuint shader_id = Shaders::CompileShaderCode(tar, shader->sh_code);
if (shader_id == -1)
return -1;
shader->sh_struct->is_struct_changed = false;
shader->sh_ID = shader_id;
return shader_id;
}
void RenderShader::RelinkShader(ShaderType tar /*= NONE_SHADER*/)
{
GLuint shader_id = CompileShader(tar);
if (shader_id == -1)
return;
GLuint program_id = glCreateProgram();
glAttachShader(program_id, shader_id);
glAttachShader(program_id, GetShaderID((ShaderType)(1 - tar)));
glLinkProgram(program_id);
glValidateProgram(program_id);
int link_state = -1;
glGetProgramiv(program_id, GL_LINK_STATUS, &link_state);
if (link_state != GL_TRUE) {
DEBUG("Shader Link Error");
return;
}
ResetID(tar, shader_id);
_resetProgramID(program_id);
ResetCache();
is_shader_changed = true;
}
void RenderShader::GenerateShader(ShaderType tar /*= NONE_SHADER*/)
{
ShaderUnit* shader = GetShaderUnit(tar);
if (!shader->sh_struct->is_struct_changed)
return;
shader->sh_struct->is_struct_changed = false;
shader->sh_code = shader->sh_struct->GenerateShader();
}
Shaders::ShaderUnit* RenderShader::GetShaderUnit(ShaderType tar /*= NONE_SHADER*/)
{
if (tar == VERTEX_SHADER || tar == FRAGMENT_SHADER)
return &shader_data[tar];
else return nullptr;
}
GLuint RenderShader::GetShaderID(ShaderType type) const
{
if (type == VERTEX_SHADER || type == FRAGMENT_SHADER)
return shader_data[type].sh_ID;
else return -1;
}
void RenderShader::ResetID(ShaderType type, GLuint id)
{
ShaderUnit* shader = GetShaderUnit(type);
if (shader->sh_ID != id) {
glDeleteShader(shader->sh_ID);
}
shader->sh_ID = id;
}
void RenderShader::LocalDebug() const
{
#ifdef _DEBUG
for (const auto& [name, loc] : _uniforms_cache)
DEBUG(name + " : " + std::to_string(loc));
#endif
}
FastLoadShader::FastLoadShader(const std::string& vert, const std::string& frag /*= ""*/)
{
vert_name = vert;
frag_name = frag == "" ? vert : frag;
std::string vert_code = Shaders::ReadShaderFile(VERTEX_SHADER, vert_name);
std::string frag_code = Shaders::ReadShaderFile(FRAGMENT_SHADER, frag_name);
CreatShader(vert_code, frag_code);
}
FastLoadShader::FastLoadShader()
{
}
FastLoadShader::~FastLoadShader()
{
}
void FastLoadShader::CreatShader(const std::string& verShader, const std::string& fragShader)
{
program_id = glCreateProgram();
vs_id = CompileShaderCode(VERTEX_SHADER, verShader);
fs_id = CompileShaderCode(FRAGMENT_SHADER, fragShader);
glAttachShader(program_id, vs_id);
glAttachShader(program_id, fs_id);
glLinkProgram(program_id);
glValidateProgram(program_id);
}
GLuint FastLoadShader::GetShaderID(ShaderType type) const
{
switch (type)
{
case VERTEX_SHADER:
return vs_id;
case FRAGMENT_SHADER:
return fs_id;
default:
return -1;
}
}
void FastLoadShader::LocalDebug() const
{
#ifdef _DEBUG
DEBUG(fast_shaders.verShader);
DEBUG(fast_shaders.fragShader);
#endif
}
std::unordered_map<std::string, std::shared_ptr<ChainedShader>> ChainedShader::chain_sh_list = {};
ChainedShader::ChainedShader(const std::vector<std::string>& chain)
{
_idx_to_type.reserve(chain.size());
shader_chain.reserve(chain.size());
LOOP(chain.size()) {
shader_chain.emplace_back(Shaders::ParseFileEXT(chain[i]), chain[i]);
_type_to_idx[shader_chain[i].sh_type] = i;
_idx_to_type.emplace_back(shader_chain[i].sh_type);
}
CreatShader();
}
ChainedShader::ChainedShader()
{
}
ChainedShader::~ChainedShader()
{
}
void ChainedShader::CreatShader()
{
program_id = glCreateProgram();
for (auto& node : shader_chain) {
std::string code = Shaders::ReadShaderFile(node.sh_type, node.sh_name);
node.sh_ID = Shaders::CompileShaderCode(node.sh_type, code);
node.sh_code = code;
}
for (const auto& node : shader_chain) {
glAttachShader(program_id, node.sh_ID);
}
glLinkProgram(program_id);
glValidateProgram(program_id);
}
ChainedShader& ChainedShader::ImportShader(const std::vector<std::string>& chain)
{
std::string _name = "";
for (auto& n : chain)
_name += n + "-";
if (chain_sh_list.find(_name) != chain_sh_list.end())
return *chain_sh_list[_name].get();
chain_sh_list[_name] = std::make_shared<ChainedShader>(chain);
return *chain_sh_list[_name].get();
}
GLuint ChainedShader::CompileShader(ShaderType type)
{
ShaderUnit* node = GetShaderUnit(type);
if (node == nullptr)
return -1;
return Shaders::CompileShaderCode(node->sh_type, node->sh_code);
}
void ChainedShader::RelinkShader(ShaderType type)
{
GLuint shader_id = CompileShader(type);
if (shader_id == -1)
return;
GLuint program_id = glCreateProgram();
glAttachShader(program_id, shader_id);
for (auto& unit : shader_chain) {
if (unit.sh_type != type)
glAttachShader(program_id, unit.sh_ID);
}
glLinkProgram(program_id);
glValidateProgram(program_id);
int link_state = -1;
glGetProgramiv(program_id, GL_LINK_STATUS, &link_state);
if (link_state != GL_TRUE) {
DEBUG("Shader Link Error");
return;
}
ResetID(type, shader_id);
_resetProgramID(program_id);
ResetCache();
is_shader_changed = true;
}
Shaders::ShaderUnit* ChainedShader::GetShaderUnit(ShaderType type)
{
const int idx = _type_to_idx[type];
if (idx == -1)
return nullptr;
else
return &shader_chain[idx];
}
void ChainedShader::ParseShaderCode(const std::string& _code, ShaderType type)
{
ShaderUnit* node = GetShaderUnit(type);
if (node == nullptr)
return;
node->sh_code = _code;
}
GLuint ChainedShader::GetShaderID(ShaderType type) const
{
const int idx = _type_to_idx[type];
if (idx == -1)
return -1;
else
return shader_chain[idx].sh_ID;
}
void ChainedShader::ResetID(ShaderType type, GLuint id)
{
ShaderUnit* node = GetShaderUnit(type);
if (node != nullptr) {
if (node->sh_ID != id)
glDeleteShader(node->sh_ID);
node->sh_ID = id;
}
}
void ChainedShader::LocalDebug() const
{
#if _DEBUG
for (auto& sh : shader_chain)
DEBUG(std::get<0>(Shaders::ParseShaderType(sh.sh_type)) + " " + sh.sh_name + " " + std::to_string(sh.sh_ID));
#endif // _DEBUG
}