PostFXParams/Preset amb chroma_min/max + scan_*; presets P2026 migrats
This commit is contained in:
@@ -590,42 +590,24 @@ auto loadData(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
return Resource::Helper::loadFile(filepath);
|
||||
}
|
||||
|
||||
void Screen::setLinearUpscale(bool linear) {
|
||||
Options::video.supersampling.linear_upscale = linear;
|
||||
if (shader_backend_ && shader_backend_->isHardwareAccelerated()) {
|
||||
shader_backend_->setLinearUpscale(linear);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::setDownscaleAlgo(int algo) {
|
||||
Options::video.supersampling.downscale_algo = algo;
|
||||
if (shader_backend_ && shader_backend_->isHardwareAccelerated()) {
|
||||
shader_backend_->setDownscaleAlgo(algo);
|
||||
}
|
||||
}
|
||||
|
||||
auto Screen::getSsTextureSize() const -> std::pair<int, int> {
|
||||
if (!shader_backend_) { return {0, 0}; }
|
||||
return shader_backend_->getSsTextureSize();
|
||||
}
|
||||
|
||||
// Activa/desactiva el supersampling global (Ctrl+F4)
|
||||
void Screen::toggleSupersampling() {
|
||||
Options::video.supersampling.enabled = !Options::video.supersampling.enabled;
|
||||
if (Options::video.shader.enabled && shader_backend_ && shader_backend_->isHardwareAccelerated()) {
|
||||
applyCurrentPostFXPreset();
|
||||
}
|
||||
}
|
||||
|
||||
// Aplica los parámetros del preset actual al backend de shaders
|
||||
void Screen::applyCurrentPostFXPreset() {
|
||||
if (shader_backend_ && !Options::postfx_presets.empty()) {
|
||||
const auto& p = Options::postfx_presets[static_cast<size_t>(Options::video.shader.current_postfx_preset)];
|
||||
// Supersampling es un toggle global (Options::video.supersampling.enabled), no por preset.
|
||||
// setOversample primero: puede recrear texturas antes de que setPostFXParams
|
||||
// decida si hornear scanlines en CPU o aplicarlas en GPU.
|
||||
shader_backend_->setOversample(Options::video.supersampling.enabled ? 3 : 1);
|
||||
Rendering::PostFXParams params{.vignette = p.vignette, .scanlines = p.scanlines, .chroma = p.chroma, .mask = p.mask, .gamma = p.gamma, .curvature = p.curvature, .bleeding = p.bleeding, .flicker = p.flicker};
|
||||
Rendering::PostFXParams params{
|
||||
.vignette = p.vignette,
|
||||
.scanlines = p.scanlines,
|
||||
.chroma_min = p.chroma_min,
|
||||
.chroma_max = p.chroma_max,
|
||||
.mask = p.mask,
|
||||
.gamma = p.gamma,
|
||||
.curvature = p.curvature,
|
||||
.bleeding = p.bleeding,
|
||||
.flicker = p.flicker,
|
||||
.scan_dark_ratio = p.scan_dark_ratio,
|
||||
.scan_dark_floor = p.scan_dark_floor,
|
||||
.scan_edge_soft = p.scan_edge_soft,
|
||||
};
|
||||
shader_backend_->setPostFXParams(params);
|
||||
}
|
||||
}
|
||||
@@ -698,11 +680,9 @@ void Screen::initShaders() {
|
||||
shader_backend_->init(window_, tex, "", "");
|
||||
gpu_driver_ = shader_backend_->getDriverName();
|
||||
|
||||
// Propagar flags de vsync, integer scale, upscale y downscale al backend GPU
|
||||
// Propagar flags de vsync e integer scale al backend GPU
|
||||
shader_backend_->setVSync(Options::video.vertical_sync);
|
||||
shader_backend_->setScaleMode(Options::video.integer_scale);
|
||||
shader_backend_->setLinearUpscale(Options::video.supersampling.linear_upscale);
|
||||
shader_backend_->setDownscaleAlgo(Options::video.supersampling.downscale_algo);
|
||||
|
||||
if (Options::video.shader.enabled) {
|
||||
applyCurrentPostFXPreset();
|
||||
|
||||
@@ -7,20 +7,28 @@
|
||||
|
||||
// PostFX uniforms pushed to fragment stage each frame.
|
||||
// Must match the MSL struct and GLSL uniform block layout.
|
||||
// 12 floats = 48 bytes — meets Metal/Vulkan 16-byte alignment requirement.
|
||||
// 16 floats = 64 bytes (4 × vec4) — meets Metal/Vulkan 16-byte alignment.
|
||||
struct PostFXUniforms {
|
||||
// vec4 #0
|
||||
float vignette_strength; // 0 = none, ~0.8 = subtle
|
||||
float chroma_strength; // 0 = off, ~0.2 = subtle chromatic aberration
|
||||
float chroma_min; // aberració cromàtica mínima (sempre present)
|
||||
float scanline_strength; // 0 = off, 1 = full
|
||||
float screen_height; // logical height in pixels (used by bleeding effect)
|
||||
float mask_strength; // 0 = off, 1 = full phosphor dot mask
|
||||
float gamma_strength; // 0 = off, 1 = full gamma 2.4/2.2 correction
|
||||
float curvature; // 0 = flat, 1 = max barrel distortion
|
||||
float bleeding; // 0 = off, 1 = max NTSC chrominance bleeding
|
||||
float pixel_scale; // physical pixels per logical pixel (vh / tex_height_)
|
||||
float time; // seconds since SDL init (SDL_GetTicks() / 1000.0f)
|
||||
float oversample; // supersampling factor (1.0 = off, 3.0 = 3×SS)
|
||||
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — keep struct at 48 bytes (3 × 16)
|
||||
// vec4 #1
|
||||
float mask_strength; // 0 = off, 1 = full phosphor dot mask
|
||||
float gamma_strength; // 0 = off, 1 = full gamma 2.4/2.2 correction
|
||||
float curvature; // 0 = flat, 1 = max barrel distortion
|
||||
float bleeding; // 0 = off, 1 = max NTSC chrominance bleeding
|
||||
// vec4 #2
|
||||
float pixel_scale; // physical pixels per logical pixel (vh / tex_height_)
|
||||
float time; // seconds since SDL init (SDL_GetTicks() / 1000.0f)
|
||||
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz
|
||||
float chroma_max; // si == chroma_min queda estàtic; si != pulsa sinusoidalment
|
||||
// vec4 #3 — paràmetres de forma de les scanlines (exposats per preset)
|
||||
float scan_dark_ratio; // fracció de subfila fosca (1/3 = 0.333 per defecte)
|
||||
float scan_dark_floor; // brillantor de la subfila fosca (0.42 per defecte)
|
||||
float scan_edge_soft; // suavitzat de la transició (0 = step dur, 1 = 1px físic)
|
||||
float pad3;
|
||||
};
|
||||
|
||||
// CrtPi uniforms pushed to fragment stage each frame.
|
||||
@@ -49,15 +57,6 @@ struct CrtPiUniforms {
|
||||
float texture_height; // Alto del canvas en píxeles (inyectado en render)
|
||||
};
|
||||
|
||||
// Downscale uniforms pushed to the Lanczos downscale fragment stage.
|
||||
// 1 int + 3 floats = 16 bytes — meets Metal/Vulkan alignment.
|
||||
struct DownscaleUniforms {
|
||||
int algorithm; // 0 = Lanczos2 (ventana 2), 1 = Lanczos3 (ventana 3)
|
||||
float pad0;
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
/**
|
||||
@@ -99,18 +98,6 @@ namespace Rendering {
|
||||
// Activa/desactiva escalado entero (integer scale)
|
||||
void setScaleMode(bool integer_scale) override;
|
||||
|
||||
// Establece factor de supersampling (1 = off, 3 = 3×SS)
|
||||
void setOversample(int factor) override;
|
||||
|
||||
// Activa/desactiva interpolación LINEAR en el upscale (false = NEAREST)
|
||||
void setLinearUpscale(bool linear) override;
|
||||
|
||||
// Selecciona algoritmo de downscale: 0=bilinear legacy, 1=Lanczos2, 2=Lanczos3
|
||||
void setDownscaleAlgo(int algo) override;
|
||||
|
||||
// Devuelve las dimensiones de la textura de supersampling (0,0 si SS desactivado)
|
||||
[[nodiscard]] auto getSsTextureSize() const -> std::pair<int, int> override;
|
||||
|
||||
// Selecciona el shader de post-procesado activo (POSTFX o CRTPI)
|
||||
void setActiveShader(ShaderType type) override;
|
||||
|
||||
@@ -137,42 +124,30 @@ namespace Rendering {
|
||||
Uint32 num_uniform_buffers) -> SDL_GPUShader*;
|
||||
|
||||
auto createPipeline() -> bool;
|
||||
auto createCrtPiPipeline() -> bool; // Pipeline dedicado para el shader CrtPi
|
||||
auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_
|
||||
auto recreateScaledTexture(int factor) -> bool; // Recrea scaled_texture_ para factor dado
|
||||
static auto calcSsFactor(float zoom) -> int; // Primer múltiplo de 3 >= zoom (mín 3)
|
||||
auto createCrtPiPipeline() -> bool; // Pipeline dedicado para el shader CrtPi
|
||||
auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_
|
||||
// Devuelve el mejor present mode disponible: IMMEDIATE > MAILBOX > VSYNC
|
||||
[[nodiscard]] auto bestPresentMode(bool vsync) const -> SDL_GPUPresentMode;
|
||||
|
||||
SDL_Window* window_ = nullptr;
|
||||
SDL_GPUDevice* device_ = nullptr;
|
||||
SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass (→ swapchain o → postfx_texture_)
|
||||
SDL_GPUGraphicsPipeline* crtpi_pipeline_ = nullptr; // CrtPi pass (→ swapchain directo, sin SS)
|
||||
SDL_GPUGraphicsPipeline* postfx_offscreen_pipeline_ = nullptr; // PostFX → postfx_texture_ (B8G8R8A8, solo con Lanczos)
|
||||
SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr; // Upscale pass (solo con SS)
|
||||
SDL_GPUGraphicsPipeline* downscale_pipeline_ = nullptr; // Lanczos downscale (solo con SS + algo > 0)
|
||||
SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_)
|
||||
SDL_GPUTexture* scaled_texture_ = nullptr; // Upscale target (game×factor), solo con SS
|
||||
SDL_GPUTexture* postfx_texture_ = nullptr; // PostFX output a resolución escalada, solo con Lanczos
|
||||
SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass → swapchain
|
||||
SDL_GPUGraphicsPipeline* crtpi_pipeline_ = nullptr; // CrtPi pass → swapchain
|
||||
SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_)
|
||||
SDL_GPUTransferBuffer* upload_buffer_ = nullptr;
|
||||
SDL_GPUSampler* sampler_ = nullptr; // NEAREST
|
||||
SDL_GPUSampler* linear_sampler_ = nullptr; // LINEAR
|
||||
SDL_GPUSampler* sampler_ = nullptr; // NEAREST
|
||||
|
||||
PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F};
|
||||
PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_min = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .chroma_max = 0.15F, .scan_dark_ratio = 0.333F, .scan_dark_floor = 0.42F, .scan_edge_soft = 1.0F};
|
||||
CrtPiUniforms crtpi_uniforms_{.scanline_weight = 6.0F, .scanline_gap_brightness = 0.12F, .bloom_factor = 3.5F, .input_gamma = 2.4F, .output_gamma = 2.2F, .mask_brightness = 0.80F, .curvature_x = 0.05F, .curvature_y = 0.10F, .mask_type = 2, .enable_scanlines = 1, .enable_multisample = 1, .enable_gamma = 1};
|
||||
ShaderType active_shader_ = ShaderType::POSTFX; // Shader de post-procesado activo
|
||||
|
||||
int game_width_ = 0; // Dimensiones originales del canvas
|
||||
int game_height_ = 0;
|
||||
int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado
|
||||
int oversample_ = 1; // SS on/off (1 = off, >1 = on)
|
||||
int downscale_algo_ = 1; // 0 = bilinear legacy, 1 = Lanczos2, 2 = Lanczos3
|
||||
std::string driver_name_;
|
||||
std::string preferred_driver_; // Driver preferido; vacío = auto (SDL elige)
|
||||
bool is_initialized_ = false;
|
||||
bool vsync_ = true;
|
||||
bool integer_scale_ = false;
|
||||
bool linear_upscale_ = false; // Upscale NEAREST (false) o LINEAR (true)
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -19,12 +19,19 @@ namespace Rendering {
|
||||
struct PostFXParams {
|
||||
float vignette = 0.0F; // Intensidad de la viñeta
|
||||
float scanlines = 0.0F; // Intensidad de las scanlines
|
||||
float chroma = 0.0F; // Aberración cromática
|
||||
// Aberració cromàtica — varia entre min i max via sinusoidal; si coincideixen
|
||||
// queda estàtica. min > 0 garanteix que la imatge mai sigui lliure de chroma.
|
||||
float chroma_min = 0.0F;
|
||||
float chroma_max = 0.0F;
|
||||
float mask = 0.0F; // Máscara de fósforo RGB
|
||||
float gamma = 0.0F; // Corrección gamma (blend 0=off, 1=full)
|
||||
float curvature = 0.0F; // Curvatura barrel CRT
|
||||
float bleeding = 0.0F; // Sangrado de color NTSC
|
||||
float flicker = 0.0F; // Parpadeo de fósforo CRT ~50 Hz
|
||||
// Forma de les scanlines — 3 subpíxels per fila lògica per defecte.
|
||||
float scan_dark_ratio = 0.333F; // fracció obscura (1/3)
|
||||
float scan_dark_floor = 0.42F; // brillantor subfila fosca
|
||||
float scan_edge_soft = 1.0F; // 0 = step dur; 1 = suavitzat 1 px físic
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -110,34 +117,6 @@ namespace Rendering {
|
||||
*/
|
||||
virtual void setScaleMode(bool /*integer_scale*/) {}
|
||||
|
||||
/**
|
||||
* @brief Establece el factor de supersampling (1 = off, 3 = 3× SS)
|
||||
* Con factor > 1, la textura GPU se crea a game×factor resolución y
|
||||
* las scanlines se hornean en CPU (uploadPixels). El sampler usa LINEAR.
|
||||
*/
|
||||
virtual void setOversample(int /*factor*/) {}
|
||||
|
||||
/**
|
||||
* @brief Activa/desactiva interpolación LINEAR en el paso de upscale (SS).
|
||||
* Por defecto NEAREST (false). Solo tiene efecto con supersampling activo.
|
||||
*/
|
||||
virtual void setLinearUpscale(bool /*linear*/) {}
|
||||
[[nodiscard]] virtual auto isLinearUpscale() const -> bool { return false; }
|
||||
|
||||
/**
|
||||
* @brief Selecciona el algoritmo de downscale tras el PostFX (SS activo).
|
||||
* 0 = bilinear legacy (comportamiento actual, sin textura intermedia),
|
||||
* 1 = Lanczos2 (ventana 2, ~25 muestras), 2 = Lanczos3 (ventana 3, ~49 muestras).
|
||||
*/
|
||||
virtual void setDownscaleAlgo(int /*algo*/) {}
|
||||
[[nodiscard]] virtual auto getDownscaleAlgo() const -> int { return 0; }
|
||||
|
||||
/**
|
||||
* @brief Devuelve las dimensiones de la textura de supersampling.
|
||||
* @return Par (ancho, alto) en píxeles; (0, 0) si SS está desactivado.
|
||||
*/
|
||||
[[nodiscard]] virtual auto getSsTextureSize() const -> std::pair<int, int> { return {0, 0}; }
|
||||
|
||||
/**
|
||||
* @brief Verifica si el backend está usando aceleración por hardware
|
||||
* @return true si usa aceleración (OpenGL/Metal/Vulkan)
|
||||
|
||||
+27
-48
@@ -323,31 +323,6 @@ namespace Options {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: carga la sección supersampling desde YAML
|
||||
void loadSupersamplingConfigFromYaml(const fkyaml::node& ss_node) {
|
||||
if (ss_node.contains("enabled")) {
|
||||
try {
|
||||
video.supersampling.enabled = ss_node["enabled"].get_value<bool>();
|
||||
} catch (...) {
|
||||
video.supersampling.enabled = Defaults::Video::SUPERSAMPLING;
|
||||
}
|
||||
}
|
||||
if (ss_node.contains("linear_upscale")) {
|
||||
try {
|
||||
video.supersampling.linear_upscale = ss_node["linear_upscale"].get_value<bool>();
|
||||
} catch (...) {
|
||||
video.supersampling.linear_upscale = Defaults::Video::LINEAR_UPSCALE;
|
||||
}
|
||||
}
|
||||
if (ss_node.contains("downscale_algo")) {
|
||||
try {
|
||||
video.supersampling.downscale_algo = ss_node["downscale_algo"].get_value<int>();
|
||||
} catch (...) {
|
||||
video.supersampling.downscale_algo = Defaults::Video::DOWNSCALE_ALGO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: carga la sección shader desde YAML
|
||||
void loadShaderConfigFromYaml(const fkyaml::node& sh_node) {
|
||||
if (sh_node.contains("enabled")) {
|
||||
@@ -437,9 +412,6 @@ namespace Options {
|
||||
if (vid.contains("gpu")) {
|
||||
loadGPUConfigFromYaml(vid["gpu"]);
|
||||
}
|
||||
if (vid.contains("supersampling")) {
|
||||
loadSupersamplingConfigFromYaml(vid["supersampling"]);
|
||||
}
|
||||
if (vid.contains("shader")) {
|
||||
loadShaderConfigFromYaml(vid["shader"]);
|
||||
}
|
||||
@@ -811,10 +783,6 @@ namespace Options {
|
||||
file << " gpu:\n";
|
||||
file << " acceleration: " << (video.gpu.acceleration ? "true" : "false") << " # Usar aceleración hardware GPU (false = SDL fallback)\n";
|
||||
file << " preferred_driver: \"" << video.gpu.preferred_driver << "\" # Driver GPU específico (empty = auto, aplica solo si gpu_acceleration: true)\n";
|
||||
file << " supersampling:\n";
|
||||
file << " enabled: " << (video.supersampling.enabled ? "true" : "false") << "\n";
|
||||
file << " linear_upscale: " << (video.supersampling.linear_upscale ? "true" : "false") << "\n";
|
||||
file << " downscale_algo: " << video.supersampling.downscale_algo << " # 0=bilinear, 1=Lanczos2, 2=Lanczos3\n";
|
||||
file << " shader:\n";
|
||||
file << " enabled: " << (video.shader.enabled ? "true" : "false") << "\n";
|
||||
file << " current_shader: " << (video.shader.current_shader == Rendering::ShaderType::CRTPI ? "crtpi" : "postfx") << "\n";
|
||||
@@ -939,12 +907,16 @@ namespace Options {
|
||||
}
|
||||
parseFloatField(p, "vignette", preset.vignette);
|
||||
parseFloatField(p, "scanlines", preset.scanlines);
|
||||
parseFloatField(p, "chroma", preset.chroma);
|
||||
parseFloatField(p, "chroma_min", preset.chroma_min);
|
||||
parseFloatField(p, "chroma_max", preset.chroma_max);
|
||||
parseFloatField(p, "mask", preset.mask);
|
||||
parseFloatField(p, "gamma", preset.gamma);
|
||||
parseFloatField(p, "curvature", preset.curvature);
|
||||
parseFloatField(p, "bleeding", preset.bleeding);
|
||||
parseFloatField(p, "flicker", preset.flicker);
|
||||
parseFloatField(p, "scan_dark_ratio", preset.scan_dark_ratio);
|
||||
parseFloatField(p, "scan_dark_floor", preset.scan_dark_floor);
|
||||
parseFloatField(p, "scan_edge_soft", preset.scan_edge_soft);
|
||||
// Nota: 'supersampling' era un campo por-preset (eliminado). Si existe
|
||||
// en el fichero del usuario se ignora silenciosamente (compatible).
|
||||
postfx_presets.push_back(preset);
|
||||
@@ -984,19 +956,21 @@ namespace Options {
|
||||
file << "# Each preset defines the intensity of post-processing effects (0.0 to 1.0).\n";
|
||||
file << "# vignette: screen darkening at the edges\n";
|
||||
file << "# scanlines: horizontal scanline effect\n";
|
||||
file << "# chroma: chromatic aberration (RGB color fringing)\n";
|
||||
file << "# chroma_min/max: chromatic aberration (RGB color fringing)\n";
|
||||
file << "# min == max → estàtic; min != max → pulsa sinusoïdalment entre els dos\n";
|
||||
file << "# mask: phosphor dot mask (RGB subpixel pattern)\n";
|
||||
file << "# gamma: gamma correction input 2.4 / output 2.2\n";
|
||||
file << "# curvature: CRT barrel distortion\n";
|
||||
file << "# bleeding: NTSC horizontal colour bleeding\n";
|
||||
file << "# flicker: phosphor CRT flicker ~50 Hz (0.0 = off, 1.0 = max)\n";
|
||||
file << "# Note: supersampling is a global toggle in config.yaml, not per-preset.\n";
|
||||
file << "# scan_dark_ratio/floor/edge_soft: forma analítica de les scanlines\n";
|
||||
file << "\n";
|
||||
file << "presets:\n";
|
||||
file << " - name: \"CRT\"\n";
|
||||
file << " vignette: 0.6\n";
|
||||
file << " scanlines: 0.7\n";
|
||||
file << " chroma: 0.15\n";
|
||||
file << " chroma_min: 0.15\n";
|
||||
file << " chroma_max: 0.15\n";
|
||||
file << " mask: 0.6\n";
|
||||
file << " gamma: 0.8\n";
|
||||
file << " curvature: 0.0\n";
|
||||
@@ -1005,7 +979,8 @@ namespace Options {
|
||||
file << " - name: \"NTSC\"\n";
|
||||
file << " vignette: 0.4\n";
|
||||
file << " scanlines: 0.5\n";
|
||||
file << " chroma: 0.2\n";
|
||||
file << " chroma_min: 0.2\n";
|
||||
file << " chroma_max: 0.2\n";
|
||||
file << " mask: 0.4\n";
|
||||
file << " gamma: 0.5\n";
|
||||
file << " curvature: 0.0\n";
|
||||
@@ -1014,7 +989,8 @@ namespace Options {
|
||||
file << " - name: \"CURVED\"\n";
|
||||
file << " vignette: 0.5\n";
|
||||
file << " scanlines: 0.6\n";
|
||||
file << " chroma: 0.1\n";
|
||||
file << " chroma_min: 0.1\n";
|
||||
file << " chroma_max: 0.1\n";
|
||||
file << " mask: 0.5\n";
|
||||
file << " gamma: 0.7\n";
|
||||
file << " curvature: 0.8\n";
|
||||
@@ -1023,7 +999,8 @@ namespace Options {
|
||||
file << " - name: \"SCANLINES\"\n";
|
||||
file << " vignette: 0.0\n";
|
||||
file << " scanlines: 0.8\n";
|
||||
file << " chroma: 0.0\n";
|
||||
file << " chroma_min: 0.0\n";
|
||||
file << " chroma_max: 0.0\n";
|
||||
file << " mask: 0.0\n";
|
||||
file << " gamma: 0.0\n";
|
||||
file << " curvature: 0.0\n";
|
||||
@@ -1032,7 +1009,8 @@ namespace Options {
|
||||
file << " - name: \"SUBTLE\"\n";
|
||||
file << " vignette: 0.3\n";
|
||||
file << " scanlines: 0.4\n";
|
||||
file << " chroma: 0.05\n";
|
||||
file << " chroma_min: 0.05\n";
|
||||
file << " chroma_max: 0.05\n";
|
||||
file << " mask: 0.0\n";
|
||||
file << " gamma: 0.3\n";
|
||||
file << " curvature: 0.0\n";
|
||||
@@ -1041,7 +1019,8 @@ namespace Options {
|
||||
file << " - name: \"CRT LIVE\"\n";
|
||||
file << " vignette: 0.5\n";
|
||||
file << " scanlines: 0.6\n";
|
||||
file << " chroma: 0.3\n";
|
||||
file << " chroma_min: 0.3\n";
|
||||
file << " chroma_max: 0.3\n";
|
||||
file << " mask: 0.3\n";
|
||||
file << " gamma: 0.4\n";
|
||||
file << " curvature: 0.3\n";
|
||||
@@ -1052,14 +1031,14 @@ namespace Options {
|
||||
|
||||
std::cout << "PostFX file created with defaults: " << postfx_file_path << '\n';
|
||||
|
||||
// Cargar los presets recién creados
|
||||
// Cargar los presets recién creados (chroma estàtic: min==max).
|
||||
postfx_presets.clear();
|
||||
postfx_presets.push_back({"CRT", 0.6F, 0.7F, 0.3F, 0.6F, 0.8F, 0.0F, 0.0F, 0.0F});
|
||||
postfx_presets.push_back({"NTSC", 0.4F, 0.5F, 0.2F, 0.4F, 0.5F, 0.0F, 0.6F, 0.0F});
|
||||
postfx_presets.push_back({"CURVED", 0.5F, 0.6F, 0.1F, 0.5F, 0.7F, 0.8F, 0.0F, 0.0F});
|
||||
postfx_presets.push_back({"SCANLINES", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F});
|
||||
postfx_presets.push_back({"SUBTLE", 0.3F, 0.4F, 0.05F, 0.0F, 0.3F, 0.0F, 0.0F, 0.0F});
|
||||
postfx_presets.push_back({"CRT LIVE", 0.5F, 0.6F, 0.3F, 0.3F, 0.4F, 0.3F, 0.4F, 0.8F});
|
||||
postfx_presets.push_back({.name = "CRT", .vignette = 0.6F, .scanlines = 0.7F, .chroma_min = 0.15F, .chroma_max = 0.15F, .mask = 0.6F, .gamma = 0.8F, .curvature = 0.0F, .bleeding = 0.0F, .flicker = 0.0F});
|
||||
postfx_presets.push_back({.name = "NTSC", .vignette = 0.4F, .scanlines = 0.5F, .chroma_min = 0.2F, .chroma_max = 0.2F, .mask = 0.4F, .gamma = 0.5F, .curvature = 0.0F, .bleeding = 0.6F, .flicker = 0.0F});
|
||||
postfx_presets.push_back({.name = "CURVED", .vignette = 0.5F, .scanlines = 0.6F, .chroma_min = 0.1F, .chroma_max = 0.1F, .mask = 0.5F, .gamma = 0.7F, .curvature = 0.8F, .bleeding = 0.0F, .flicker = 0.0F});
|
||||
postfx_presets.push_back({.name = "SCANLINES", .vignette = 0.0F, .scanlines = 0.8F, .chroma_min = 0.0F, .chroma_max = 0.0F, .mask = 0.0F, .gamma = 0.0F, .curvature = 0.0F, .bleeding = 0.0F, .flicker = 0.0F});
|
||||
postfx_presets.push_back({.name = "SUBTLE", .vignette = 0.3F, .scanlines = 0.4F, .chroma_min = 0.05F, .chroma_max = 0.05F, .mask = 0.0F, .gamma = 0.3F, .curvature = 0.0F, .bleeding = 0.0F, .flicker = 0.0F});
|
||||
postfx_presets.push_back({.name = "CRT LIVE", .vignette = 0.5F, .scanlines = 0.6F, .chroma_min = 0.3F, .chroma_max = 0.3F, .mask = 0.3F, .gamma = 0.4F, .curvature = 0.3F, .bleeding = 0.4F, .flicker = 0.8F});
|
||||
video.shader.current_postfx_preset = 0;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -79,13 +79,6 @@ namespace Options {
|
||||
std::string preferred_driver; // Driver GPU preferido; vacío = auto. Aplica en el próximo arranque.
|
||||
};
|
||||
|
||||
// Estructura para las opciones de supersampling
|
||||
struct Supersampling {
|
||||
bool enabled{Defaults::Video::SUPERSAMPLING}; // Indica si el supersampling 3× está activo
|
||||
bool linear_upscale{Defaults::Video::LINEAR_UPSCALE}; // Upscale LINEAR (true) o NEAREST (false)
|
||||
int downscale_algo{Defaults::Video::DOWNSCALE_ALGO}; // 0=bilinear, 1=Lanczos2, 2=Lanczos3
|
||||
};
|
||||
|
||||
// Estructura para las opciones de shader (dentro de Video)
|
||||
struct ShaderConfig {
|
||||
bool enabled{Defaults::Video::SHADER_ENABLED}; // Indica si se usan shaders de post-procesado
|
||||
@@ -108,7 +101,6 @@ namespace Options {
|
||||
std::string info; // Información sobre el modo de vídeo
|
||||
Border border{}; // Borde de la pantalla
|
||||
GPU gpu{}; // Opciones de aceleración GPU
|
||||
Supersampling supersampling{}; // Opciones de supersampling
|
||||
ShaderConfig shader{}; // Opciones de shader post-procesado
|
||||
};
|
||||
|
||||
@@ -157,12 +149,18 @@ namespace Options {
|
||||
std::string name; // Nombre del preset
|
||||
float vignette{0.6F}; // Intensidad de la viñeta (0.0 = ninguna, 1.0 = máxima)
|
||||
float scanlines{0.7F}; // Intensidad de las scanlines (0.0 = desactivadas, 1.0 = máximas)
|
||||
float chroma{0.15F}; // Intensidad de la aberración cromática (0.0 = ninguna, 1.0 = máxima)
|
||||
// Aberració cromàtica: min == max → estàtic; min != max → pulsa sinusoïdalment.
|
||||
float chroma_min{0.15F};
|
||||
float chroma_max{0.15F};
|
||||
float mask{0.0F}; // Intensidad de la máscara de fósforo RGB (0.0 = desactivada, 1.0 = máxima)
|
||||
float gamma{0.0F}; // Corrección gamma input 2.4 / output 2.2 (0.0 = off, 1.0 = plena)
|
||||
float curvature{0.0F}; // Distorsión barrel CRT (0.0 = plana, 1.0 = máxima curvatura)
|
||||
float bleeding{0.0F}; // Sangrado de color NTSC horizontal Y/C (0.0 = off, 1.0 = máximo)
|
||||
float flicker{0.0F}; // Parpadeo de fósforo CRT ~50 Hz (0.0 = off, 1.0 = máximo)
|
||||
// Forma de les scanlines — 3 subpíxels per fila lògica per defecte.
|
||||
float scan_dark_ratio{0.333F};
|
||||
float scan_dark_floor{0.42F};
|
||||
float scan_edge_soft{1.0F};
|
||||
};
|
||||
|
||||
// Estructura para un preset del shader CRT-Pi
|
||||
|
||||
Reference in New Issue
Block a user