Presets PostFX carregats de shaders/postfx.yaml; Screen aplica params (v0.5.0)

This commit is contained in:
JailDesigner committed 2026-04-18 23:02:06 +02:00
1 parent 6c8ef9ff44
commit 26b4d9e610
7 files changed
+194 -4

No files matched your search

+139 -1
View File
@@ -1,5 +1,6 @@
#include "game/options.hpp"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
@@ -71,6 +72,15 @@ namespace {
if (node.contains("preferred_driver")) { Options::video.gpu.preferred_driver = node["preferred_driver"].get_value<std::string>(); }
}
void parseShader(const fkyaml::node& video_node) {
if (!video_node.contains("shader")) { return; }
const auto& node = video_node["shader"];
if (node.contains("enabled")) { Options::video.shader.enabled = node["enabled"].get_value<bool>(); }
if (node.contains("current_postfx_preset")) {
Options::video.shader.current_postfx_preset = node["current_postfx_preset"].get_value<std::string>();
}
}
void parseVideo(const fkyaml::node& yaml) {
if (!yaml.contains("video")) { return; }
const auto& node = yaml["video"];
@@ -82,6 +92,7 @@ namespace {
Options::video.texture_filter = filterFromString(node["texture_filter"].get_value<std::string>());
}
parseGpu(node);
parseShader(node);
}
void parseMusic(const fkyaml::node& audio_node) {
@@ -107,6 +118,55 @@ namespace {
parseSound(node);
}
// Presets per defecte de PostFX, usats quan el fitxer postfx.yaml no existeix.
auto defaultPostFXPresets() -> std::vector<Options::PostFXPreset> {
return {
{.name = "off"}, // passthrough (tot a 0)
{.name = "crt",
.vignette = 0.6F,
.scanlines = 0.7F,
.chroma = 0.15F,
.mask = 0.6F,
.gamma = 0.8F,
.curvature = 0.0F,
.bleeding = 0.0F,
.flicker = 0.0F},
{.name = "ntsc",
.vignette = 0.4F,
.scanlines = 0.5F,
.chroma = 0.25F,
.mask = 0.3F,
.gamma = 0.6F,
.curvature = 0.0F,
.bleeding = 0.4F,
.flicker = 0.1F},
};
}
void parsePostFXPreset(const fkyaml::node& node, Options::PostFXPreset& preset) {
if (node.contains("name")) { preset.name = node["name"].get_value<std::string>(); }
if (node.contains("vignette")) { preset.vignette = node["vignette"].get_value<float>(); }
if (node.contains("scanlines")) { preset.scanlines = node["scanlines"].get_value<float>(); }
if (node.contains("chroma")) { preset.chroma = node["chroma"].get_value<float>(); }
if (node.contains("mask")) { preset.mask = node["mask"].get_value<float>(); }
if (node.contains("gamma")) { preset.gamma = node["gamma"].get_value<float>(); }
if (node.contains("curvature")) { preset.curvature = node["curvature"].get_value<float>(); }
if (node.contains("bleeding")) { preset.bleeding = node["bleeding"].get_value<float>(); }
if (node.contains("flicker")) { preset.flicker = node["flicker"].get_value<float>(); }
}
void writePostFXPreset(std::ostringstream& out, const Options::PostFXPreset& preset) {
out << " - name: \"" << preset.name << "\"\n";
out << " vignette: " << preset.vignette << "\n";
out << " scanlines: " << preset.scanlines << "\n";
out << " chroma: " << preset.chroma << "\n";
out << " mask: " << preset.mask << "\n";
out << " gamma: " << preset.gamma << "\n";
out << " curvature: " << preset.curvature << "\n";
out << " bleeding: " << preset.bleeding << "\n";
out << " flicker: " << preset.flicker << "\n";
}
} // namespace
namespace Options {
@@ -166,7 +226,10 @@ namespace Options {
out << " texture_filter: \"" << filterToString(video.texture_filter) << "\"\n";
out << " gpu:\n";
out << " acceleration: " << (video.gpu.acceleration ? "true" : "false") << "\n";
out << " preferred_driver: \"" << video.gpu.preferred_driver << "\"\n\n";
out << " preferred_driver: \"" << video.gpu.preferred_driver << "\"\n";
out << " shader:\n";
out << " enabled: " << (video.shader.enabled ? "true" : "false") << "\n";
out << " current_postfx_preset: \"" << video.shader.current_postfx_preset << "\"\n\n";
out << "audio:\n";
out << " enabled: " << (audio.enabled ? "true" : "false") << "\n";
@@ -193,4 +256,79 @@ namespace Options {
return config;
}
void setPostFXFile(const std::string& path) {
postfx_file_path = path;
}
auto loadPostFXFromFile() -> bool {
if (postfx_file_path.empty()) { return false; }
const std::string CONTENT = readFileOrEmpty(postfx_file_path);
if (CONTENT.empty()) {
postfx_presets = defaultPostFXPresets();
return savePostFXToFile();
}
try {
auto yaml = fkyaml::node::deserialize(CONTENT);
if (!yaml.contains("presets") || !yaml["presets"].is_sequence()) {
postfx_presets = defaultPostFXPresets();
return savePostFXToFile();
}
postfx_presets.clear();
for (const auto& preset_node : yaml["presets"]) {
PostFXPreset preset;
parsePostFXPreset(preset_node, preset);
postfx_presets.push_back(preset);
}
if (postfx_presets.empty()) {
postfx_presets = defaultPostFXPresets();
return savePostFXToFile();
}
return true;
} catch (const std::exception& e) {
std::cerr << "Options: error parsejant postfx.yaml: " << e.what() << '\n';
std::cerr << "Options: reescrivint el fitxer amb presets per defecte.\n";
postfx_presets = defaultPostFXPresets();
return savePostFXToFile();
}
}
auto savePostFXToFile() -> bool {
if (postfx_file_path.empty()) { return false; }
std::ostringstream out;
out << "# Presets PostFX per a AEE 2026. Editable a mà.\n";
out << "# Els noms han de coincidir amb config.yaml > video.shader.current_postfx_preset.\n";
out << "presets:\n";
for (const auto& preset : postfx_presets) {
writePostFXPreset(out, preset);
}
return writeFile(postfx_file_path, out.str());
}
auto buildPostFXParams() -> Rendering::PostFXParams {
// Si el shader està deshabilitat, retornem params a zero → passthrough.
if (!video.shader.enabled) { return {}; }
const auto IT = std::ranges::find_if(postfx_presets,
[](const PostFXPreset& preset) { return preset.name == video.shader.current_postfx_preset; });
if (IT == postfx_presets.end()) {
std::cerr << "Options: preset PostFX \"" << video.shader.current_postfx_preset << "\" no trobat; aplicant passthrough.\n";
return {};
}
return {
.vignette = IT->vignette,
.scanlines = IT->scanlines,
.chroma = IT->chroma,
.mask = IT->mask,
.gamma = IT->gamma,
.curvature = IT->curvature,
.bleeding = IT->bleeding,
.flicker = IT->flicker,
};
}
} // namespace Options
+28
View File
@@ -1,8 +1,10 @@
#pragma once
#include <string>
#include <vector>
#include "core/rendering/screen.hpp"
#include "core/rendering/shader_backend.hpp"
#include "utils/defaults.hpp"
// Gestor de configuració del joc. És l'ÚNIC lloc que coneix YAML i la ruta
@@ -21,11 +23,30 @@ namespace Options {
std::string preferred_driver{Defaults::Video::GPU_PREFERRED_DRIVER};
};
struct Shader {
bool enabled{Defaults::Video::SHADER_ENABLED};
std::string current_postfx_preset{Defaults::Video::POSTFX_DEFAULT_PRESET};
};
struct Video {
bool vsync{Defaults::Video::VSYNC};
Defaults::ScalingMode scaling_mode{Defaults::Video::SCALING_MODE};
Defaults::TextureFilter texture_filter{Defaults::Video::TEXTURE_FILTER};
Gpu gpu{};
Shader shader{};
};
// Preset d'efectes PostFX (un per entrada a postfx.yaml).
struct PostFXPreset {
std::string name;
float vignette{0.0F};
float scanlines{0.0F};
float chroma{0.0F};
float mask{0.0F};
float gamma{0.0F};
float curvature{0.0F};
float bleeding{0.0F};
float flicker{0.0F};
};
struct Music {
@@ -49,16 +70,23 @@ namespace Options {
// el programa sense necessitar un .cpp extra per a cada una) ---
inline std::string config_version{};
inline std::string config_file_path{};
inline std::string postfx_file_path{};
inline Window window{};
inline Video video{};
inline Audio audio{};
inline std::vector<PostFXPreset> postfx_presets{};
// --- API pública ---
void setConfigFile(const std::string& path);
auto loadFromFile() -> bool;
auto saveToFile() -> bool;
void setPostFXFile(const std::string& path);
auto loadPostFXFromFile() -> bool;
auto savePostFXToFile() -> bool;
// --- Builders per als subsistemes ---
[[nodiscard]] auto buildScreenConfig() -> Screen::Config;
[[nodiscard]] auto buildPostFXParams() -> Rendering::PostFXParams;
} // namespace Options