add post-effect-slot resource & add gfx.posteffects library
This commit is contained in:
parent
c3bc084e76
commit
64039f0e43
@ -189,6 +189,8 @@ constexpr const char* to_string(ResourceType type) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case ResourceType::CAMERA:
|
case ResourceType::CAMERA:
|
||||||
return "camera";
|
return "camera";
|
||||||
|
case ResourceType::POST_EFFECT_SLOT:
|
||||||
|
return "post-effect-slot";
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
@ -197,6 +199,8 @@ constexpr const char* to_string(ResourceType type) {
|
|||||||
inline std::optional<ResourceType> ResourceType_from(std::string_view str) {
|
inline std::optional<ResourceType> ResourceType_from(std::string_view str) {
|
||||||
if (str == "camera") {
|
if (str == "camera") {
|
||||||
return ResourceType::CAMERA;
|
return ResourceType::CAMERA;
|
||||||
|
} else if (str == "post-effect-slot") {
|
||||||
|
return ResourceType::POST_EFFECT_SLOT;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,11 @@ class ContentPackRuntime;
|
|||||||
|
|
||||||
enum class ContentType { NONE, BLOCK, ITEM, ENTITY, GENERATOR };
|
enum class ContentType { NONE, BLOCK, ITEM, ENTITY, GENERATOR };
|
||||||
|
|
||||||
enum class ResourceType : size_t { CAMERA, LAST = CAMERA };
|
enum class ResourceType : size_t {
|
||||||
|
CAMERA,
|
||||||
|
POST_EFFECT_SLOT,
|
||||||
|
LAST = POST_EFFECT_SLOT
|
||||||
|
};
|
||||||
|
|
||||||
inline constexpr auto RESOURCE_TYPES_COUNT =
|
inline constexpr auto RESOURCE_TYPES_COUNT =
|
||||||
static_cast<size_t>(ResourceType::LAST) + 1;
|
static_cast<size_t>(ResourceType::LAST) + 1;
|
||||||
|
|||||||
@ -42,7 +42,9 @@ LevelScreen::LevelScreen(
|
|||||||
)
|
)
|
||||||
: Screen(engine),
|
: Screen(engine),
|
||||||
world(*levelPtr->getWorld()),
|
world(*levelPtr->getWorld()),
|
||||||
postProcessing(std::make_unique<PostProcessing>()),
|
postProcessing(std::make_unique<PostProcessing>(
|
||||||
|
levelPtr->content.getIndices(ResourceType::POST_EFFECT_SLOT).size()
|
||||||
|
)),
|
||||||
gui(engine.getGUI()),
|
gui(engine.getGUI()),
|
||||||
input(engine.getInput()) {
|
input(engine.getInput()) {
|
||||||
Level* level = levelPtr.get();
|
Level* level = levelPtr.get();
|
||||||
@ -115,7 +117,9 @@ void LevelScreen::initializeContent() {
|
|||||||
for (auto& entry : content.getPacks()) {
|
for (auto& entry : content.getPacks()) {
|
||||||
initializePack(entry.second.get());
|
initializePack(entry.second.get());
|
||||||
}
|
}
|
||||||
scripting::on_frontend_init(hud.get(), renderer.get());
|
scripting::on_frontend_init(
|
||||||
|
hud.get(), renderer.get(), postProcessing.get()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
#include "PostEffect.hpp"
|
#include "PostEffect.hpp"
|
||||||
|
|
||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
|
#include "data/dv_util.hpp"
|
||||||
|
|
||||||
PostEffect::Param::Param() : type(Type::FLOAT) {}
|
PostEffect::Param::Param() : type(Type::FLOAT) {}
|
||||||
|
|
||||||
PostEffect::Param::Param(Type type, Value defValue)
|
PostEffect::Param::Param(Type type, Value defValue)
|
||||||
: type(type), defValue(std::move(defValue)) {
|
: type(type), defValue(defValue), value(defValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PostEffect::PostEffect(
|
PostEffect::PostEffect(
|
||||||
std::unique_ptr<Shader> shader,
|
std::shared_ptr<Shader> shader,
|
||||||
std::unordered_map<std::string, Param> params
|
std::unordered_map<std::string, Param> params
|
||||||
)
|
)
|
||||||
: shader(std::move(shader)), params(std::move(params)) {
|
: shader(std::move(shader)), params(std::move(params)) {
|
||||||
@ -18,9 +19,65 @@ PostEffect::PostEffect(
|
|||||||
Shader& PostEffect::use() {
|
Shader& PostEffect::use() {
|
||||||
shader->use();
|
shader->use();
|
||||||
shader->uniform1f("u_intensity", intensity);
|
shader->uniform1f("u_intensity", intensity);
|
||||||
|
for (auto& [name, param] : params) {
|
||||||
|
if (!param.dirty) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (param.type) {
|
||||||
|
case Param::Type::FLOAT:
|
||||||
|
shader->uniform1f(name, std::get<float>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC2:
|
||||||
|
shader->uniform2f(name, std::get<glm::vec2>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC3:
|
||||||
|
shader->uniform3f(name, std::get<glm::vec3>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC4:
|
||||||
|
shader->uniform4f(name, std::get<glm::vec4>(param.value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
param.dirty = false;
|
||||||
|
}
|
||||||
return *shader;
|
return *shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float PostEffect::getIntensity() const {
|
||||||
|
return intensity;
|
||||||
|
}
|
||||||
|
|
||||||
void PostEffect::setIntensity(float value) {
|
void PostEffect::setIntensity(float value) {
|
||||||
intensity = value;
|
intensity = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<int n>
|
||||||
|
static void set_value(PostEffect::Param::Value& dst, const dv::value& value) {
|
||||||
|
glm::vec<n, float> vec;
|
||||||
|
dv::get_vec(value, vec);
|
||||||
|
dst = vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostEffect::setParam(const std::string& name, const dv::value& value) {
|
||||||
|
const auto& found = params.find(name);
|
||||||
|
if (found == params.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& param = found->second;
|
||||||
|
switch (param.type) {
|
||||||
|
case Param::Type::FLOAT:
|
||||||
|
param.value = static_cast<float>(value.asNumber());
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC2:
|
||||||
|
set_value<2>(param.value, value);
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC3:
|
||||||
|
set_value<3>(param.value, value);
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC4:
|
||||||
|
set_value<4>(param.value, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
param.dirty = true;
|
||||||
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "data/dv_fwd.hpp"
|
||||||
|
|
||||||
class Shader;
|
class Shader;
|
||||||
|
|
||||||
class PostEffect {
|
class PostEffect {
|
||||||
@ -16,25 +18,32 @@ public:
|
|||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
Value defValue;
|
Value defValue;
|
||||||
|
Value value;
|
||||||
|
bool dirty = true;
|
||||||
|
|
||||||
Param();
|
Param();
|
||||||
Param(Type type, Value defValue);
|
Param(Type type, Value defValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
PostEffect(
|
PostEffect(
|
||||||
std::unique_ptr<Shader> shader,
|
std::shared_ptr<Shader> shader,
|
||||||
std::unordered_map<std::string, Param> params
|
std::unordered_map<std::string, Param> params
|
||||||
);
|
);
|
||||||
|
|
||||||
|
explicit PostEffect(const PostEffect&) = default;
|
||||||
|
|
||||||
Shader& use();
|
Shader& use();
|
||||||
|
|
||||||
|
float getIntensity() const;
|
||||||
void setIntensity(float value);
|
void setIntensity(float value);
|
||||||
|
|
||||||
|
void setParam(const std::string& name, const dv::value& value);
|
||||||
|
|
||||||
bool isActive() {
|
bool isActive() {
|
||||||
return intensity > 1e-4f;
|
return intensity > 1e-4f;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Shader> shader;
|
std::shared_ptr<Shader> shader;
|
||||||
std::unordered_map<std::string, Param> params;
|
std::unordered_map<std::string, Param> params;
|
||||||
float intensity = 0.0f;
|
float intensity = 0.0f;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
PostProcessing::PostProcessing() {
|
PostProcessing::PostProcessing(size_t effectSlotsCount)
|
||||||
|
: effectSlots(effectSlotsCount) {
|
||||||
// Fullscreen quad mesh bulding
|
// Fullscreen quad mesh bulding
|
||||||
float vertices[] {
|
float vertices[] {
|
||||||
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
||||||
@ -77,6 +78,14 @@ void PostProcessing::render(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostProcessing::setEffect(size_t slot, std::shared_ptr<PostEffect> effect) {
|
||||||
|
effectSlots.at(slot) = std::move(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
PostEffect* PostProcessing::getEffect(size_t slot) {
|
||||||
|
return effectSlots.at(slot).get();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<ImageData> PostProcessing::toImage() {
|
std::unique_ptr<ImageData> PostProcessing::toImage() {
|
||||||
return fbo->getTexture()->readData();
|
return fbo->getTexture()->readData();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class PostProcessing {
|
|||||||
std::unique_ptr<Mesh> quadMesh;
|
std::unique_ptr<Mesh> quadMesh;
|
||||||
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
||||||
public:
|
public:
|
||||||
PostProcessing();
|
PostProcessing(size_t effectSlotsCount);
|
||||||
~PostProcessing();
|
~PostProcessing();
|
||||||
|
|
||||||
/// @brief Prepare and bind framebuffer
|
/// @brief Prepare and bind framebuffer
|
||||||
@ -34,6 +34,10 @@ public:
|
|||||||
/// @throws std::runtime_error if use(...) wasn't called before
|
/// @throws std::runtime_error if use(...) wasn't called before
|
||||||
void render(const DrawContext& context, const Assets& assets, float timer);
|
void render(const DrawContext& context, const Assets& assets, float timer);
|
||||||
|
|
||||||
|
void setEffect(size_t slot, std::shared_ptr<PostEffect> effect);
|
||||||
|
|
||||||
|
PostEffect* getEffect(size_t slot);
|
||||||
|
|
||||||
/// @brief Make an image from the last rendered frame
|
/// @brief Make an image from the last rendered frame
|
||||||
std::unique_ptr<ImageData> toImage();
|
std::unique_ptr<ImageData> toImage();
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,7 @@ extern const luaL_Reg networklib[];
|
|||||||
extern const luaL_Reg packlib[];
|
extern const luaL_Reg packlib[];
|
||||||
extern const luaL_Reg particleslib[]; // gfx.particles
|
extern const luaL_Reg particleslib[]; // gfx.particles
|
||||||
extern const luaL_Reg playerlib[];
|
extern const luaL_Reg playerlib[];
|
||||||
|
extern const luaL_Reg posteffectslib[]; // gfx.posteffects
|
||||||
extern const luaL_Reg quatlib[];
|
extern const luaL_Reg quatlib[];
|
||||||
extern const luaL_Reg text3dlib[]; // gfx.text3d
|
extern const luaL_Reg text3dlib[]; // gfx.text3d
|
||||||
extern const luaL_Reg timelib[];
|
extern const luaL_Reg timelib[];
|
||||||
@ -46,7 +47,7 @@ extern const luaL_Reg utf8lib[];
|
|||||||
extern const luaL_Reg vec2lib[]; // vecn.cpp
|
extern const luaL_Reg vec2lib[]; // vecn.cpp
|
||||||
extern const luaL_Reg vec3lib[]; // vecn.cpp
|
extern const luaL_Reg vec3lib[]; // vecn.cpp
|
||||||
extern const luaL_Reg vec4lib[]; // vecn.cpp
|
extern const luaL_Reg vec4lib[]; // vecn.cpp
|
||||||
extern const luaL_Reg weatherlib[];
|
extern const luaL_Reg weatherlib[]; // gfx.weather
|
||||||
extern const luaL_Reg worldlib[];
|
extern const luaL_Reg worldlib[];
|
||||||
extern const luaL_Reg yamllib[];
|
extern const luaL_Reg yamllib[];
|
||||||
|
|
||||||
|
|||||||
68
src/logic/scripting/lua/libs/libposteffects.cpp
Normal file
68
src/logic/scripting/lua/libs/libposteffects.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "libhud.hpp"
|
||||||
|
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
|
#include "content/Content.hpp"
|
||||||
|
#include "graphics/core/PostEffect.hpp"
|
||||||
|
#include "graphics/core/PostProcessing.hpp"
|
||||||
|
|
||||||
|
using namespace scripting;
|
||||||
|
|
||||||
|
static int l_index(lua::State* L) {
|
||||||
|
auto name = lua::require_string(L, 1);
|
||||||
|
auto& indices = content->getIndices(ResourceType::POST_EFFECT_SLOT);
|
||||||
|
return lua::pushinteger(L, indices.indexOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_set_effect(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
auto name = lua::require_string(L, 2);
|
||||||
|
auto& assets = *engine->getAssets();
|
||||||
|
auto effect = std::make_shared<PostEffect>(assets.require<PostEffect>(name));
|
||||||
|
post_processing->setEffect(index, std::move(effect));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_get_intensity(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
auto effect = post_processing->getEffect(index);
|
||||||
|
return lua::pushnumber(L, effect ? effect->getIntensity() : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_set_intensity(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
float value = lua::tonumber(L, 2);
|
||||||
|
post_processing->getEffect(index)->setIntensity(value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_is_active(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
auto effect = post_processing->getEffect(index);
|
||||||
|
return lua::pushboolean(L, effect ? effect->isActive() : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_set_params(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
auto table = lua::tovalue(L, 2);
|
||||||
|
if (!table.isObject()) {
|
||||||
|
throw std::runtime_error("params table expected");
|
||||||
|
}
|
||||||
|
auto effect = post_processing->getEffect(index);
|
||||||
|
if (effect == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : table.asObject()) {
|
||||||
|
effect->setParam(key, value);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg posteffectslib[] = {
|
||||||
|
{"index", lua::wrap<l_index>},
|
||||||
|
{"set_effect", lua::wrap<l_set_effect>},
|
||||||
|
{"get_intensity", lua::wrap<l_get_intensity>},
|
||||||
|
{"set_intensity", lua::wrap<l_set_intensity>},
|
||||||
|
{"is_active", lua::wrap<l_is_active>},
|
||||||
|
{"set_params", lua::wrap<l_set_params>},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
@ -19,6 +19,7 @@ static debug::Logger logger("scripting-hud");
|
|||||||
|
|
||||||
Hud* scripting::hud = nullptr;
|
Hud* scripting::hud = nullptr;
|
||||||
WorldRenderer* scripting::renderer = nullptr;
|
WorldRenderer* scripting::renderer = nullptr;
|
||||||
|
PostProcessing* scripting::post_processing = nullptr;
|
||||||
|
|
||||||
static void load_script(const std::string& name) {
|
static void load_script(const std::string& name) {
|
||||||
auto file = io::path("res:scripts") / name;
|
auto file = io::path("res:scripts") / name;
|
||||||
@ -28,9 +29,12 @@ static void load_script(const std::string& name) {
|
|||||||
lua::execute(lua::get_main_state(), 0, src, file.string());
|
lua::execute(lua::get_main_state(), 0, src, file.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
void scripting::on_frontend_init(
|
||||||
|
Hud* hud, WorldRenderer* renderer, PostProcessing* postProcessing
|
||||||
|
) {
|
||||||
scripting::hud = hud;
|
scripting::hud = hud;
|
||||||
scripting::renderer = renderer;
|
scripting::renderer = renderer;
|
||||||
|
scripting::post_processing = postProcessing;
|
||||||
|
|
||||||
auto L = lua::get_main_state();
|
auto L = lua::get_main_state();
|
||||||
|
|
||||||
@ -39,6 +43,7 @@ void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
|||||||
lua::openlib(L, "gfx", "particles", particleslib);
|
lua::openlib(L, "gfx", "particles", particleslib);
|
||||||
lua::openlib(L, "gfx", "weather", weatherlib);
|
lua::openlib(L, "gfx", "weather", weatherlib);
|
||||||
lua::openlib(L, "gfx", "text3d", text3dlib);
|
lua::openlib(L, "gfx", "text3d", text3dlib);
|
||||||
|
lua::openlib(L, "gfx", "posteffects", posteffectslib);
|
||||||
|
|
||||||
load_script("hud_classes.lua");
|
load_script("hud_classes.lua");
|
||||||
|
|
||||||
@ -85,6 +90,7 @@ void scripting::on_frontend_close() {
|
|||||||
|
|
||||||
scripting::renderer = nullptr;
|
scripting::renderer = nullptr;
|
||||||
scripting::hud = nullptr;
|
scripting::hud = nullptr;
|
||||||
|
scripting::post_processing = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scripting::load_hud_script(
|
void scripting::load_hud_script(
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
class Hud;
|
class Hud;
|
||||||
class WorldRenderer;
|
class WorldRenderer;
|
||||||
|
class PostProcessing;
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class UINode;
|
class UINode;
|
||||||
@ -18,8 +19,11 @@ namespace gui {
|
|||||||
namespace scripting {
|
namespace scripting {
|
||||||
extern Hud *hud;
|
extern Hud *hud;
|
||||||
extern WorldRenderer* renderer;
|
extern WorldRenderer* renderer;
|
||||||
|
extern PostProcessing* post_processing;
|
||||||
|
|
||||||
void on_frontend_init(Hud* hud, WorldRenderer* renderer);
|
void on_frontend_init(
|
||||||
|
Hud* hud, WorldRenderer* renderer, PostProcessing* postProcessing
|
||||||
|
);
|
||||||
void on_frontend_render();
|
void on_frontend_render();
|
||||||
void on_frontend_close();
|
void on_frontend_close();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user