move shaders into .glsl files and add #include feature

This commit is contained in:
2019-02-21 19:26:40 +01:00
parent 16eb9de358
commit eaab9c79e5
47 changed files with 1124 additions and 777 deletions

View File

@@ -1,11 +1,122 @@
#include "pch.h"
#include "log.h"
#include "shader.h"
#include "asset.h"
std::map<kShader, Shader> ShaderManager::m_shaders;
Shader* ShaderManager::m_current;
bool ShaderManager::ext_framebuffer_fetch = false;
std::string Shader::read(const std::string& path)
{
Asset a;
std::string ret;
if (a.open(path.c_str()))
{
std::regex reg_include(R"!(#include "([^"]+)")!");
std::string data((char*)a.read_all(), a.m_len);
// split path
std::string name, base, ext;
std::regex reg_path(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
std::smatch m;
if (std::regex_search(path, m, reg_path))
{
base = m[1].str();
name = m[2].str();
ext = m[3].str();
}
for (const auto& l : split(data, '\n'))
{
std::smatch m;
if (std::regex_search(l, m, reg_include))
{
std::string inc = base + "/" + m[1].str();
if (Asset::exist(inc.c_str()))
{
std::string subdata = read(inc);
ret.append(subdata + "\n");
}
}
else
{
ret.append(l + "\n");
}
}
}
return ret;
}
void Shader::parse_error(const char* msg, const char* code)
{
auto code_lines = split(code, '\n');
auto error_lines = split(msg, '\n');
std::smatch m;
std::regex r(R"(\((\d+)\))");
for (const auto& line : error_lines)
{
LOG("%s", line.c_str());
if (std::regex_search(line, m, r))
{
int ln = std::stoi(m[1].str());
if (ln < code_lines.size())
{
int n = 2;
int s = std::max(ln - n, 1);
int e = std::min((int)code_lines.size() - 1, ln + n);
for (int i = s; i < e; i++)
{
LOG("- line %02d: %s", i, code_lines[i - 1].c_str());
}
}
}
}
}
bool Shader::load(const std::string& path)
{
std::string data = read(path);
if (data.empty()) return false;
std::map<std::string, std::shared_ptr<std::string>> sections;
std::shared_ptr<std::string> current_section = nullptr;
std::regex reg_section(R"!(\[\[(.*)\]\])!");
for (const auto& l : split(data, '\n'))
{
std::smatch m;
if (std::regex_search(l, m, reg_section))
{
std::string section_name = m[1].str();
if (!sections[section_name])
sections[section_name] = std::make_shared<std::string>();
current_section = sections[section_name];
}
else
{
// create an un-named section
if (!current_section)
current_section = sections[""] = std::make_shared<std::string>();
current_section->append(l + "\n");
}
}
if (sections.find("vertex") != sections.end() && sections.find("fragment") != sections.end())
{
*sections["vertex"] = SHADER_VERSION + *sections["vertex"];
*sections["fragment"] = SHADER_VERSION + *sections["fragment"];
return create(sections["vertex"]->c_str(), sections["fragment"]->c_str());
}
else
{
LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str());
}
m_path = path;
return false;
}
bool Shader::create(const char* vertex, const char* fragment)
{
GLint status;
@@ -24,7 +135,10 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
LOG("VERTEX SHADER:\n%s", infolog);
{
LOG("\nVERTEX SHADER:");
parse_error(infolog, vertex);
}
if (status == 0)
{
glDeleteShader(vs);
@@ -43,7 +157,10 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
LOG("FRAGMENT SHADER:\n%s", infolog);
{
LOG("\nFRAGMENT SHADER:");
parse_error(infolog, fragment);
}
if (status == 0)
{
glDeleteShader(vs);
@@ -159,6 +276,12 @@ GLint Shader::GetAttribLocation(const char* name)
return glGetAttribLocation(prog, name);
}
bool ShaderManager::load(kShader id, const std::string& path)
{
m_shaders[id].name = id;
return m_shaders[id].load(path);
}
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
{
m_shaders[id].name = id;