shader auto reload
This commit is contained in:
14
src/app.cpp
14
src/app.cpp
@@ -505,6 +505,7 @@ void App::update(float dt)
|
|||||||
{
|
{
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
static float rec_timer = 0.f;
|
static float rec_timer = 0.f;
|
||||||
|
static float reload_timer = 0.f;
|
||||||
|
|
||||||
// avoid multiple threads to update the scene
|
// avoid multiple threads to update the scene
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
@@ -524,17 +525,18 @@ void App::update(float dt)
|
|||||||
//glClear(GL_COLOR_BUFFER_BIT);
|
//glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
//if (!canvas->m_mouse_captured)
|
//if (!canvas->m_mouse_captured)
|
||||||
|
#if _DEBUG && (_WIN32 || __OSX__)
|
||||||
|
reload_timer += dt;
|
||||||
|
if (reload_timer > 1.0)
|
||||||
{
|
{
|
||||||
#if _WIN32 || __OSX__
|
reload_timer = 0;
|
||||||
|
ShaderManager::reload();
|
||||||
layout.reload();
|
layout.reload();
|
||||||
#endif
|
|
||||||
if (auto* main = layout[main_id])
|
if (auto* main = layout[main_id])
|
||||||
{
|
|
||||||
main->update(width, height, zoom);
|
main->update(width, height, zoom);
|
||||||
//stroke->update_controls();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
static glm::vec4 color_button_normal{ .1, .1, .1, 1 };
|
static glm::vec4 color_button_normal{ .1, .1, .1, 1 };
|
||||||
static glm::vec4 color_button_hlight{ 1, .0, .0, 1 };
|
static glm::vec4 color_button_hlight{ 1, .0, .0, 1 };
|
||||||
|
|||||||
@@ -220,12 +220,15 @@ glm::uint8_t* Asset::read_all()
|
|||||||
void Asset::close()
|
void Asset::close()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
AAsset_close(m_asset);
|
if (m_asset)
|
||||||
|
AAsset_close(m_asset);
|
||||||
|
m_asset = nullptr;
|
||||||
#else
|
#else
|
||||||
if (m_fp)
|
if (m_fp)
|
||||||
fclose(m_fp);
|
fclose(m_fp);
|
||||||
if (m_data)
|
if (m_data)
|
||||||
delete m_data;
|
delete m_data;
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
|
m_fp = nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,6 @@ public:
|
|||||||
bool open(const char* path);
|
bool open(const char* path);
|
||||||
uint8_t* read_all();
|
uint8_t* read_all();
|
||||||
void close();
|
void close();
|
||||||
|
~Asset() { close(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
#include <stb/stb_image_write.h>
|
#include <stb/stb_image_write.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef _DEBUG
|
||||||
#pragma comment (lib, "libcurl_debug.lib")
|
#pragma comment (lib, "libcurl_debug.lib")
|
||||||
#else
|
#else
|
||||||
#pragma comment (lib, "libcurl.lib")
|
#pragma comment (lib, "libcurl.lib")
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ bool RTT::create(int width, int height, int tex/* = -1*/, GLint internal_format)
|
|||||||
|
|
||||||
void RTT::bindFramebuffer()
|
void RTT::bindFramebuffer()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef _DEBUG
|
||||||
if (bound)
|
if (bound)
|
||||||
{
|
{
|
||||||
LOG("framebuffer bound twice!");
|
LOG("framebuffer bound twice!");
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ std::string Shader::read(const std::string& path)
|
|||||||
std::string ret;
|
std::string ret;
|
||||||
if (a.open(path.c_str()))
|
if (a.open(path.c_str()))
|
||||||
{
|
{
|
||||||
|
struct stat tmp_info;
|
||||||
|
if (stat(path.c_str(), &tmp_info) == 0)
|
||||||
|
m_deps[path] = tmp_info;
|
||||||
|
|
||||||
std::regex reg_include(R"!(#include "([^"]+)")!");
|
std::regex reg_include(R"!(#include "([^"]+)")!");
|
||||||
std::string data((char*)a.read_all(), a.m_len);
|
std::string data((char*)a.read_all(), a.m_len);
|
||||||
|
|
||||||
@@ -105,18 +109,46 @@ bool Shader::load(const std::string& path)
|
|||||||
{
|
{
|
||||||
*sections["vertex"] = SHADER_VERSION + *sections["vertex"];
|
*sections["vertex"] = SHADER_VERSION + *sections["vertex"];
|
||||||
*sections["fragment"] = SHADER_VERSION + *sections["fragment"];
|
*sections["fragment"] = SHADER_VERSION + *sections["fragment"];
|
||||||
return create(sections["vertex"]->c_str(), sections["fragment"]->c_str());
|
if (create(sections["vertex"]->c_str(), sections["fragment"]->c_str()))
|
||||||
|
{
|
||||||
|
m_path = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str());
|
LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_path = path;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Shader::reload()
|
||||||
|
{
|
||||||
|
if (m_path.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool dirty = false;
|
||||||
|
struct stat tmp_info;
|
||||||
|
for (auto& d : m_deps)
|
||||||
|
{
|
||||||
|
if (stat(d.first.c_str(), &tmp_info) != 0)
|
||||||
|
continue;
|
||||||
|
if (tmp_info.st_mtime > d.second.st_mtime)
|
||||||
|
{
|
||||||
|
d.second = tmp_info;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
|
LOG("reload shader %s", m_path.c_str());
|
||||||
|
destroy();
|
||||||
|
return load(m_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Shader::create(const char* vertex, const char* fragment)
|
bool Shader::create(const char* vertex, const char* fragment)
|
||||||
{
|
{
|
||||||
GLint status;
|
GLint status;
|
||||||
@@ -136,7 +168,7 @@ bool Shader::create(const char* vertex, const char* fragment)
|
|||||||
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
|
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
|
||||||
if (infolen > 0)
|
if (infolen > 0)
|
||||||
{
|
{
|
||||||
LOG("\nVERTEX SHADER:");
|
LOG("\nVERTEX SHADER: %s", m_path.c_str());
|
||||||
parse_error(infolog, vertex);
|
parse_error(infolog, vertex);
|
||||||
}
|
}
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
@@ -158,7 +190,7 @@ bool Shader::create(const char* vertex, const char* fragment)
|
|||||||
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
|
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
|
||||||
if (infolen > 0)
|
if (infolen > 0)
|
||||||
{
|
{
|
||||||
LOG("\nFRAGMENT SHADER:");
|
LOG("\nFRAGMENT SHADER: %s", m_path.c_str());
|
||||||
parse_error(infolog, fragment);
|
parse_error(infolog, fragment);
|
||||||
}
|
}
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
@@ -200,7 +232,7 @@ bool Shader::create(const char* vertex, const char* fragment)
|
|||||||
glGetProgramiv(ps, GL_LINK_STATUS, &status);
|
glGetProgramiv(ps, GL_LINK_STATUS, &status);
|
||||||
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
|
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
|
||||||
if (infolen > 0)
|
if (infolen > 0)
|
||||||
LOG("LINK SHADER:\n%s", infolog);
|
LOG("LINK SHADER: %s\n%s", m_path.c_str(), infolog);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
glDeleteProgram(ps);
|
glDeleteProgram(ps);
|
||||||
@@ -228,6 +260,18 @@ bool Shader::create(const char* vertex, const char* fragment)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::destroy()
|
||||||
|
{
|
||||||
|
if (prog)
|
||||||
|
{
|
||||||
|
glUseProgram(0);
|
||||||
|
glDeleteProgram(prog);
|
||||||
|
prog = 0;
|
||||||
|
}
|
||||||
|
m_umap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Shader::use()
|
void Shader::use()
|
||||||
{
|
{
|
||||||
glUseProgram(prog);
|
glUseProgram(prog);
|
||||||
@@ -282,6 +326,14 @@ bool ShaderManager::load(kShader id, const std::string& path)
|
|||||||
return m_shaders[id].load(path);
|
return m_shaders[id].load(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShaderManager::reload()
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
for (auto& s : m_shaders)
|
||||||
|
success &= s.second.reload();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
|
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
|
||||||
{
|
{
|
||||||
m_shaders[id].name = id;
|
m_shaders[id].name = id;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ enum class kShader : uint16_t
|
|||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
{
|
{
|
||||||
|
std::map<std::string, struct stat> m_deps;
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::map<kShaderUniform, GLuint> m_umap;
|
std::map<kShaderUniform, GLuint> m_umap;
|
||||||
GLuint prog;
|
GLuint prog;
|
||||||
@@ -82,7 +83,9 @@ public:
|
|||||||
kShader name;
|
kShader name;
|
||||||
void parse_error(const char* msg, const char* code);
|
void parse_error(const char* msg, const char* code);
|
||||||
bool load(const std::string& path);
|
bool load(const std::string& path);
|
||||||
|
bool reload();
|
||||||
bool create(const char* vertex, const char* fragment);
|
bool create(const char* vertex, const char* fragment);
|
||||||
|
void destroy();
|
||||||
void use();
|
void use();
|
||||||
void u_vec4(kShaderUniform id, const glm::vec4& v);
|
void u_vec4(kShaderUniform id, const glm::vec4& v);
|
||||||
void u_vec3(kShaderUniform id, const glm::vec3& v);
|
void u_vec3(kShaderUniform id, const glm::vec3& v);
|
||||||
@@ -100,6 +103,7 @@ class ShaderManager
|
|||||||
public:
|
public:
|
||||||
static bool ext_framebuffer_fetch;
|
static bool ext_framebuffer_fetch;
|
||||||
static bool load(kShader id, const std::string& path);
|
static bool load(kShader id, const std::string& path);
|
||||||
|
static bool reload();
|
||||||
static bool create(kShader id, const char* vertex, const char* fragment);
|
static bool create(kShader id, const char* vertex, const char* fragment);
|
||||||
static void use(kShader id);
|
static void use(kShader id);
|
||||||
static void use(const char* name);
|
static void use(const char* name);
|
||||||
|
|||||||
Reference in New Issue
Block a user