From cbeacb9f53f152b3be9c28c04a313ea981185e8c Mon Sep 17 00:00:00 2001 From: luboslenco Date: Sat, 11 Jul 2026 20:42:14 +0200 Subject: [PATCH] paint: expose gamma and contrast --- paint/shaders/compositor_pass.kong | 9 +++++++++ paint/sources/config.c | 4 ++++ paint/sources/startup.c | 16 +++++++++++++++- paint/sources/types.h | 2 ++ paint/sources/ui/box_preferences.c | 14 ++++++++++++++ paint/sources/uniforms.c | 6 ++++++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/paint/shaders/compositor_pass.kong b/paint/shaders/compositor_pass.kong index 1eb64c20..6c33a1e4 100644 --- a/paint/shaders/compositor_pass.kong +++ b/paint/shaders/compositor_pass.kong @@ -5,6 +5,8 @@ const constants: { grain_strength: float; tonemap_strength: float; // 0.0 or 1.0 lut_size: float; + contrast_strength: float; + gamma_strength: float; }; #[set(everything)] @@ -84,6 +86,13 @@ fun compositor_pass_frag(input: vert_out): float4 { color.rgb = lerp3(color.rgb, tonemap_filmic(color.rgb), constants.tonemap_strength); } + // Contrast + color.rgb = (color.rgb - float3(0.5, 0.5, 0.5)) * constants.contrast_strength + float3(0.5, 0.5, 0.5); + + // Gamma + var inv_gamma: float = 1.0 / max(constants.gamma_strength, 0.01); + color.rgb = pow3(max3(color.rgb, float3(0.0, 0.0, 0.0)), float3(inv_gamma, inv_gamma, inv_gamma)); + return color; } diff --git a/paint/sources/config.c b/paint/sources/config.c index 6074046e..e7f3059a 100644 --- a/paint/sources/config.c +++ b/paint/sources/config.c @@ -75,6 +75,8 @@ void config_save() { json_encode_f32("rp_bloom", g_config->rp_bloom); json_encode_f32("rp_vignette", g_config->rp_vignette); json_encode_f32("rp_grain", g_config->rp_grain); + json_encode_f32("rp_contrast", g_config->rp_contrast); + json_encode_f32("rp_gamma", g_config->rp_gamma); json_encode_string("lut_path", g_config->lut_path); json_encode_bool("texture_filter", g_config->texture_filter); json_encode_string_array("recent_projects", g_config->recent_projects); @@ -180,6 +182,8 @@ void config_init() { g_config->rp_bloom = 0.0; g_config->rp_vignette = 0.2; g_config->rp_grain = 0.09; + g_config->rp_contrast = 1.0; + g_config->rp_gamma = 1.0; g_config->lut_path = ""; g_config->texture_filter = true; #if defined(IRON_ANDROID) || defined(IRON_IOS) diff --git a/paint/sources/startup.c b/paint/sources/startup.c index 22403b75..cf0c31dc 100644 --- a/paint/sources/startup.c +++ b/paint/sources/startup.c @@ -3082,7 +3082,7 @@ scene_t *startup_get_scene(void) { ve->data = "float2"; sc->vertex_elements->buffer[0] = ve; } - sc->constants = (shader_const_t_array_t *)any_array_create(4); + sc->constants = (shader_const_t_array_t *)any_array_create(6); { shader_const_t *c = (shader_const_t *)gc_alloc(sizeof(shader_const_t)); c->name = "vignette_strength"; @@ -3111,6 +3111,20 @@ scene_t *startup_get_scene(void) { c->link = "_lut_size"; sc->constants->buffer[3] = c; } + { + shader_const_t *c = (shader_const_t *)gc_alloc(sizeof(shader_const_t)); + c->name = "contrast_strength"; + c->type = "float"; + c->link = "_contrast_strength"; + sc->constants->buffer[4] = c; + } + { + shader_const_t *c = (shader_const_t *)gc_alloc(sizeof(shader_const_t)); + c->name = "gamma_strength"; + c->type = "float"; + c->link = "_gamma_strength"; + sc->constants->buffer[5] = c; + } sc->texture_units = (tex_unit_t_array_t *)any_array_create(2); { tex_unit_t *tu = (tex_unit_t *)gc_alloc(sizeof(tex_unit_t)); diff --git a/paint/sources/types.h b/paint/sources/types.h index 02c59045..689feea6 100644 --- a/paint/sources/types.h +++ b/paint/sources/types.h @@ -96,6 +96,8 @@ typedef struct config { f32 rp_bloom; f32 rp_vignette; f32 rp_grain; + f32 rp_contrast; + f32 rp_gamma; char *lut_path; // .cube bool texture_filter; // Application diff --git a/paint/sources/ui/box_preferences.c b/paint/sources/ui/box_preferences.c index f8096780..25a2b86a 100644 --- a/paint/sources/ui/box_preferences.c +++ b/paint/sources/ui/box_preferences.c @@ -670,6 +670,20 @@ void box_preferences_viewport_tab() { } } + ui_handle_t *h_contrast = ui_handle(__ID__); + h_contrast->f = g_config->rp_contrast; + g_config->rp_contrast = ui_slider(h_contrast, tr("Contrast"), 0.0, 2.0, true, 100.0, true, UI_ALIGN_RIGHT, true); + if (h_contrast->changed) { + g_context->ddirty = 2; + } + + ui_handle_t *h_gamma = ui_handle(__ID__); + h_gamma->f = g_config->rp_gamma; + g_config->rp_gamma = ui_slider(h_gamma, tr("Gamma"), 0.0, 2.0, true, 100.0, true, UI_ALIGN_RIGHT, true); + if (h_gamma->changed) { + g_context->ddirty = 2; + } + ui_handle_t *h_vignette = ui_handle(__ID__); h_vignette->f = g_config->rp_vignette; g_config->rp_vignette = ui_slider(h_vignette, tr("Vignette"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true); diff --git a/paint/sources/uniforms.c b/paint/sources/uniforms.c index 1fdf0e03..44b46dcf 100644 --- a/paint/sources/uniforms.c +++ b/paint/sources/uniforms.c @@ -42,6 +42,12 @@ f32 uniforms_ext_f32_link(object_t *object, material_data_t *mat, char *link) { else if (string_equals(link, "_grain_strength")) { return g_config->rp_grain; } + else if (string_equals(link, "_contrast_strength")) { + return g_config->rp_contrast; + } + else if (string_equals(link, "_gamma_strength")) { + return g_config->rp_gamma; + } else if (string_equals(link, "_tonemap_strength")) { bool tonemap = g_context->viewport_mode == VIEWPORT_MODE_LIT || g_context->viewport_mode == VIEWPORT_MODE_PATH_TRACE; return tonemap ? 1.0 : 0.0;