Shaders now are managed by a manger that can do hot reloading and it also will detect a bad shader and use an ERROR shader so you know it's busted visually.
This commit is contained in:
parent
a5b8e411e3
commit
35ced58cc9
14 changed files with 144 additions and 13 deletions
18
assets/shaders/ui_error.frag
Normal file
18
assets/shaders/ui_error.frag
Normal file
|
@ -0,0 +1,18 @@
|
|||
uniform vec2 u_resolution;
|
||||
uniform vec2 u_mouse;
|
||||
uniform float u_duration;
|
||||
uniform float u_time;
|
||||
uniform float u_time_end;
|
||||
uniform sampler2D texture;
|
||||
uniform bool is_shape;
|
||||
|
||||
void main() {
|
||||
if(is_shape) {
|
||||
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
gl_FragColor = gl_Color * color;
|
||||
} else {
|
||||
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
|
||||
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
gl_FragColor = gl_Color * color * pixel;
|
||||
}
|
||||
}
|
|
@ -73,7 +73,6 @@ constexpr wchar_t BG_TILE = L'█';
|
|||
constexpr wchar_t UI_BASE_CHAR = L'█';
|
||||
constexpr int BG_BOX_OFFSET=5;
|
||||
constexpr const char *FONT_FILE_NAME="assets/text.otf";
|
||||
constexpr const char *DEFAULT_UI_SHADER = "shaders/ui_shader.frag";
|
||||
|
||||
constexpr std::array<std::wstring, 8> COMPASS{
|
||||
// L"E", L"SE", L"S", L"SW", L"W", L"NW", L"N", L"NE"
|
||||
|
|
17
guecs.cpp
17
guecs.cpp
|
@ -1,4 +1,5 @@
|
|||
#include "guecs.hpp"
|
||||
#include "shaders.hpp"
|
||||
|
||||
namespace guecs {
|
||||
|
||||
|
@ -66,31 +67,31 @@ namespace guecs {
|
|||
}
|
||||
|
||||
void Shader::init(lel::Cell &cell) {
|
||||
ptr = std::make_shared<sf::Shader>();
|
||||
bool good = ptr->loadFromFile(name, sf::Shader::Type::Fragment);
|
||||
dbc::check(good, fmt::format("failed to load shader {}", name));
|
||||
ptr->setUniform("u_resolution", sf::Vector2f({float(cell.w), float(cell.h)}));
|
||||
|
||||
auto shader = shaders::get(name);
|
||||
shader->setUniform("u_resolution", sf::Vector2f({float(cell.w), float(cell.h)}));
|
||||
clock = std::make_shared<sf::Clock>();
|
||||
}
|
||||
|
||||
void Shader::step() {
|
||||
auto shader = shaders::get(name);
|
||||
sf::Time u_time = clock->getElapsedTime();
|
||||
float current_time = u_time.asSeconds();
|
||||
|
||||
if(current_time < u_time_end) {
|
||||
ptr->setUniform("u_time", current_time);
|
||||
shader->setUniform("u_time", current_time);
|
||||
} else {
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::run() {
|
||||
auto shader = shaders::get(name);
|
||||
|
||||
active = true;
|
||||
sf::Time u_time = clock->getElapsedTime();
|
||||
u_time_end = u_time.asSeconds() + duration;
|
||||
ptr->setUniform("u_duration", duration);
|
||||
ptr->setUniform("u_time_end", u_time_end);
|
||||
shader->setUniform("u_duration", duration);
|
||||
shader->setUniform("u_time_end", u_time_end);
|
||||
}
|
||||
|
||||
UI::UI() {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "constants.hpp"
|
||||
#include "components.hpp"
|
||||
#include <any>
|
||||
#include "shaders.hpp"
|
||||
|
||||
namespace guecs {
|
||||
using std::shared_ptr, std::make_shared, std::wstring, std::string;
|
||||
|
@ -83,10 +84,9 @@ namespace guecs {
|
|||
|
||||
struct Shader {
|
||||
float duration = 0.1f;
|
||||
std::string name{DEFAULT_UI_SHADER};
|
||||
std::string name{"ui_shader"};
|
||||
float u_time_end = 0.0;
|
||||
bool active = false;
|
||||
std::shared_ptr<sf::Shader> ptr = nullptr;
|
||||
std::shared_ptr<sf::Clock> clock = nullptr;
|
||||
|
||||
void init(lel::Cell &cell);
|
||||
|
@ -199,7 +199,7 @@ namespace guecs {
|
|||
auto& shader = $world.get<Shader>(ent);
|
||||
|
||||
if(shader.active) {
|
||||
shader_ptr = shader.ptr.get();
|
||||
shader_ptr = shaders::get(shader.name);
|
||||
shader_ptr->setUniform("is_shape", is_shape);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,6 +286,7 @@ namespace gui {
|
|||
case KEY::P:
|
||||
sound::mute(false);
|
||||
$debug_ui.debug();
|
||||
shaders::reload();
|
||||
break;
|
||||
case KEY::O:
|
||||
autowalking = true;
|
||||
|
|
2
main.cpp
2
main.cpp
|
@ -5,6 +5,7 @@
|
|||
#include "ai.hpp"
|
||||
#include "animation.hpp"
|
||||
#include <iostream>
|
||||
#include "shaders.hpp"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
|
@ -12,6 +13,7 @@ int main(int argc, char* argv[]) {
|
|||
sound::init();
|
||||
ai::init("assets/ai.json");
|
||||
animation::init();
|
||||
shaders::init();
|
||||
|
||||
sound::mute(true);
|
||||
gui::FSM main;
|
||||
|
|
|
@ -114,6 +114,7 @@ sources = [
|
|||
'ritual_ui.cpp',
|
||||
'rituals.cpp',
|
||||
'save.cpp',
|
||||
'shaders.cpp',
|
||||
'shiterator.hpp',
|
||||
'sound.cpp',
|
||||
'spatialmap.cpp',
|
||||
|
@ -145,6 +146,7 @@ executable('runtests', sources + [
|
|||
'tests/matrix.cpp',
|
||||
'tests/pathing.cpp',
|
||||
'tests/rituals.cpp',
|
||||
'tests/shaders.cpp',
|
||||
'tests/sound.cpp',
|
||||
'tests/spatialmap.cpp',
|
||||
'tests/stats.cpp',
|
||||
|
|
|
@ -394,7 +394,7 @@ void Raycaster::update_level(GameLevel level) {
|
|||
|
||||
void Raycaster::init_shaders() {
|
||||
// dbc::check(sf::Shader::isAvailable(), "no shaders?!");
|
||||
bool good = $brightness.loadFromFile("shaders/modal.frag", sf::Shader::Type::Fragment);
|
||||
bool good = $brightness.loadFromFile("assets/shaders/modal.frag", sf::Shader::Type::Fragment);
|
||||
dbc::check(good, "shader could not be loaded");
|
||||
$brightness.setUniform("source", sf::Shader::CurrentTexture);
|
||||
}
|
||||
|
|
60
shaders.cpp
Normal file
60
shaders.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include "shaders.hpp"
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include "dbc.hpp"
|
||||
#include <fmt/core.h>
|
||||
#include "config.hpp"
|
||||
#include "constants.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace shaders {
|
||||
using std::shared_ptr, std::make_shared;
|
||||
|
||||
static ShaderManager SMGR;
|
||||
static bool initialized = false;
|
||||
|
||||
|
||||
bool load_shader(std::string name, nlohmann::json& settings) {
|
||||
std::string file_name = settings["file_name"];
|
||||
auto ptr = std::make_shared<sf::Shader>();
|
||||
bool good = ptr->loadFromFile(file_name, sf::Shader::Type::Fragment);
|
||||
if(good) SMGR.shaders.try_emplace(name, name, file_name, ptr);
|
||||
return good;
|
||||
}
|
||||
|
||||
void init() {
|
||||
if(!initialized) {
|
||||
initialized = true;
|
||||
Config config("assets/shaders.json");
|
||||
bool good = load_shader("ERROR", config["ERROR"]);
|
||||
dbc::check(good, "Failed to load ERROR shader. Look in assets/shaders.json");
|
||||
|
||||
for(auto& [name, settings] : config.json().items()) {
|
||||
if(name == "ERROR") continue;
|
||||
|
||||
dbc::check(!SMGR.shaders.contains(name),
|
||||
fmt::format("shader name '{}' duplicated in assets/shaders.json", name));
|
||||
good = load_shader(name, settings);
|
||||
|
||||
if(!good) {
|
||||
dbc::log(fmt::format("failed to load shader {}", name));
|
||||
SMGR.shaders.insert_or_assign(name, SMGR.shaders.at("ERROR"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sf::Shader* get(std::string name) {
|
||||
dbc::check(initialized, "you forgot to shaders::init()");
|
||||
dbc::check(SMGR.shaders.contains(name),
|
||||
fmt::format("shader name '{}' not in assets/shaders.json", name));
|
||||
|
||||
auto& rec = SMGR.shaders.at(name);
|
||||
return rec.ptr.get();
|
||||
}
|
||||
|
||||
void reload() {
|
||||
initialized = false;
|
||||
SMGR.shaders.clear();
|
||||
init();
|
||||
}
|
||||
};
|
26
shaders.hpp
Normal file
26
shaders.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include "matrix.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace shaders {
|
||||
struct Record {
|
||||
std::string name;
|
||||
std::string file_name;
|
||||
std::shared_ptr<sf::Shader> ptr = nullptr;
|
||||
};
|
||||
|
||||
struct ShaderManager {
|
||||
std::unordered_map<std::string, Record> shaders;
|
||||
};
|
||||
|
||||
void init();
|
||||
bool load_shader(std::string& name, nlohmann::json& settings);
|
||||
sf::Shader* get(std::string name);
|
||||
void reload();
|
||||
}
|
22
tests/shaders.cpp
Normal file
22
tests/shaders.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "shaders.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
TEST_CASE("shader loading/init works", "[shaders]") {
|
||||
shaders::init();
|
||||
|
||||
sf::Shader* ui_shader = shaders::get("ui_shader");
|
||||
auto other_test = shaders::get("ui_shader");
|
||||
|
||||
REQUIRE(ui_shader != nullptr);
|
||||
REQUIRE(ui_shader == other_test);
|
||||
|
||||
shaders::reload();
|
||||
|
||||
// auto after_reload = shaders::get("ui_shader");
|
||||
// REQUIRE(ui_shader != after_reload);
|
||||
// REQUIRE(other_test != after_reload);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue