move shaders into .glsl files and add #include feature
This commit is contained in:
127
src/shader.cpp
127
src/shader.cpp
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user