From 5f31dd100cff838888b6739174992cb95fadea5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Tue, 26 Mar 2024 19:13:55 +0100 Subject: [PATCH] improve srgb control --- bind/v4k.lua | 2 + demos/01-font.c | 1 + demos/06-material.c | 4 +- .../art/fx/fxGamma.fs | 0 engine/art/shaders/fs_32_4_model.glsl | 3 -- engine/art/shaders/fs_3_4_skybox.glsl | 3 -- .../art/shaders/fs_3_4_skybox_rayleigh.glsl | 3 +- engine/art/shaders/fs_font.glsl | 2 + engine/joint/v4k.h | 40 ++++++++++++++++--- engine/split/v4k_font.c | 1 + engine/split/v4k_gui.c | 4 +- engine/split/v4k_main.c | 5 +++ engine/split/v4k_render.c | 8 ++-- engine/split/v4k_renderdd.c | 3 ++ engine/split/v4k_window.c | 17 ++++++++ engine/split/v4k_window.h | 2 + engine/v4k.c | 38 +++++++++++++++--- engine/v4k.h | 2 + 18 files changed, 111 insertions(+), 27 deletions(-) rename demos/art/fx/fxTonemapZZGamma.fs => engine/art/fx/fxGamma.fs (100%) diff --git a/bind/v4k.lua b/bind/v4k.lua index 955f7ea..4e2858f 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -2040,6 +2040,8 @@ enum WINDOW_FLAGS { void window_loop_exit(); void window_title(const char *title); void window_color(unsigned color); + void window_gamma(float gamma); + float window_get_gamma(); vec2 window_canvas(); void* window_handle(); char* window_stats(); diff --git a/demos/01-font.c b/demos/01-font.c index c8caafd..981dade 100644 --- a/demos/01-font.c +++ b/demos/01-font.c @@ -2,6 +2,7 @@ int main() { window_create(75.0, WINDOW_MSAA8); + window_gamma(0); // @fixme: disable gamma correction for now // style: our aliases #define FONT_REGULAR FONT_FACE1 diff --git a/demos/06-material.c b/demos/06-material.c index 2912d0c..62ece85 100644 --- a/demos/06-material.c +++ b/demos/06-material.c @@ -37,8 +37,8 @@ int main() { // load model model_t m1 = model("suzanne.obj", MODEL_NO_ANIMATIONS); model_t m2 = model("suzanne.obj", MODEL_NO_ANIMATIONS|MODEL_MATCAPS); - // model_t m3 = model("damagedhelmet.gltf", MODEL_NO_ANIMATIONS|MODEL_PBR); - model_t m3 = model("Scutum_low.fbx", MODEL_NO_ANIMATIONS|MODEL_PBR); + model_t m3 = model("damagedhelmet.gltf", MODEL_NO_ANIMATIONS|MODEL_PBR); + // model_t m3 = model("Scutum_low.fbx", MODEL_NO_ANIMATIONS|MODEL_PBR); // model_t m4 = model("avp/scene.gltf", MODEL_NO_ANIMATIONS|MODEL_PBR); // model_t m3 = model("Cerberus_LP.FBX", MODEL_NO_ANIMATIONS|MODEL_PBR); diff --git a/demos/art/fx/fxTonemapZZGamma.fs b/engine/art/fx/fxGamma.fs similarity index 100% rename from demos/art/fx/fxTonemapZZGamma.fs rename to engine/art/fx/fxGamma.fs diff --git a/engine/art/shaders/fs_32_4_model.glsl b/engine/art/shaders/fs_32_4_model.glsl index 99090bd..4ca85c4 100644 --- a/engine/art/shaders/fs_32_4_model.glsl +++ b/engine/art/shaders/fs_32_4_model.glsl @@ -447,8 +447,6 @@ void main() { vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z)); fragcolor += vec4(col, 1.0);} #endif - - fragcolor.rgb = pow( fragcolor.rgb, vec3(1. / 2.2) ); } #endif #ifdef SHADING_PBR @@ -705,7 +703,6 @@ void main(void) // gamma correction color = pow( color, vec3(1. / 2.2) ); #endif - color = pow( color, vec3(1. / 2.2) ); // Technically this alpha may be too transparent, if there is a lot of reflected light we wouldn't // see the background, maybe we can approximate it well enough by adding a fresnel term diff --git a/engine/art/shaders/fs_3_4_skybox.glsl b/engine/art/shaders/fs_3_4_skybox.glsl index 6c72103..6c359b8 100644 --- a/engine/art/shaders/fs_3_4_skybox.glsl +++ b/engine/art/shaders/fs_3_4_skybox.glsl @@ -1,11 +1,8 @@ uniform samplerCube u_cubemap; - in vec3 v_direction; out vec4 fragcolor; - void main() { fragcolor = vec4(texture(u_cubemap, v_direction).rgb, 1.0); - fragcolor.rgb = pow(fragcolor.rgb, vec3(1.0/2.2)); } \ No newline at end of file diff --git a/engine/art/shaders/fs_3_4_skybox_rayleigh.glsl b/engine/art/shaders/fs_3_4_skybox_rayleigh.glsl index 8f09732..bf645cc 100644 --- a/engine/art/shaders/fs_3_4_skybox_rayleigh.glsl +++ b/engine/art/shaders/fs_3_4_skybox_rayleigh.glsl @@ -8,7 +8,7 @@ uniform float uMieScattering; uniform float uRayleighScaleHeight; uniform float uMieScaleHeight; uniform float uMiePreferredDirection; - +uniform float gamma; /// set:2.2 in vec3 v_direction; out vec4 fragcolor; @@ -36,6 +36,7 @@ void main() { color = 1.0 - exp(-1.0 * color); fragcolor = vec4(color, 1); + fragcolor.rgb = pow(fragcolor.rgb, vec3(gamma)); } diff --git a/engine/art/shaders/fs_font.glsl b/engine/art/shaders/fs_font.glsl index 0021e20..c727064 100644 --- a/engine/art/shaders/fs_font.glsl +++ b/engine/art/shaders/fs_font.glsl @@ -4,6 +4,7 @@ in float color_index; uniform sampler2D sampler_font; uniform sampler1D sampler_colors; uniform float num_colors; +uniform float gamma; /// set:2.2 out vec4 outColor; @@ -11,4 +12,5 @@ void main() { vec4 col = texture(sampler_colors, (color_index+0.5)/num_colors); float s = texture(sampler_font, uv).r; outColor = vec4(col.rgb, s*col.a); + outColor.rgb = pow(outColor.rgb, vec3(gamma)); } diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 18ec3a4..de958ce 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -18688,6 +18688,8 @@ API void window_loop_exit(); // exit from main loop function (emscripten onl API void window_title(const char *title); API void window_color(unsigned color); +API void window_gamma(float gamma); // 2.2 - standard, 0.0 - disables postfx pass +API float window_get_gamma(); API vec2 window_canvas(); API void* window_handle(); API char* window_stats(); @@ -363502,6 +363504,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact glUniform1f(glGetUniformLocation(f->program, "scale_factor"), factor); glUniform2fv(glGetUniformLocation(f->program, "string_offset"), 1, &offset.x); glUniform1f(glGetUniformLocation(f->program, "offset_firstline"), f->ascent*f->factor); + glUniform1f(glGetUniformLocation(f->program, "gamma"), (window_get_gamma() + !window_get_gamma())); GLint dims[4] = {0}; glGetIntegerv(GL_VIEWPORT, dims); @@ -364091,8 +364094,8 @@ API void gui_drawrect( texture_t spritesheet, vec2 tex_start, vec2 tex_end, int #define v42v2(rect) vec2(rect.x,rect.y), vec2(rect.z,rect.w) void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, vec2 start, vec2 end ) { - float gamma = 1; static int program = -1, vbo = -1, vao = -1, u_inv_gamma = -1, u_tint = -1, u_has_tex = -1, u_window_width = -1, u_window_height = -1; + float gamma = window_get_gamma(); vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1)); if( program < 0 ) { const char* vs = vfs_read("shaders/rect_2d.vs"); @@ -364119,7 +364122,7 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; glUseProgram( program ); - glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + glUniform1f( u_inv_gamma, (gamma + !gamma) ); glBindVertexArray( vao ); @@ -371664,7 +371667,7 @@ skybox_t skybox(const char *asset, int flags) { if( asset ) { int is_panorama = vfs_size( asset ); if( is_panorama ) { // is file - // stbi_hdr_to_ldr_gamma(1.2f); + stbi_hdr_to_ldr_gamma(1.2f); image_t panorama = image( asset, IMAGE_RGBA ); sky.cubemap = cubemap( panorama, 0 ); // RGBA required image_destroy(&panorama); @@ -372393,12 +372396,12 @@ bool postfx_begin(postfx *fx, int width, int height) { fbo_destroy(fx->fb[1]); // create texture, set texture parameters and content - fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[0] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[0] = fbo(fx->diffuse[0].id, fx->depth[0].id, 0); // create texture, set texture parameters and content - fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[1] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[1] = fbo(fx->diffuse[1].id, fx->depth[1].id, 0); } @@ -372501,7 +372504,7 @@ bool postfx_end(postfx *fx) { return true; } -static postfx fx; +static postfx fx, gamma_fx; int fx_load_from_mem(const char *nameid, const char *content) { do_once postfx_create(&fx, 0); return postfx_load_from_mem(&fx, nameid, content); @@ -374029,8 +374032,10 @@ static const char *dd_fs = "//" FILELINE "\n" // "precision mediump float;\n" "in vec3 out_color;\n" "out vec4 fragcolor;\n" + "uniform float gamma; /// set:2.2\n" "void main() {\n" " fragcolor = vec4(out_color, 1.0);\n" + " fragcolor.rgb = pow(fragcolor.rgb, vec3(gamma));\n" "}"; #define X(x) RGBX(x,255) @@ -374090,6 +374095,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { glUseProgram(dd_program); glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp); + glUniform1f(glGetUniformLocation(dd_program, "gamma"), (window_get_gamma() + !window_get_gamma())); static GLuint vao, vbo; if(!vao) glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -379321,6 +379327,7 @@ static char title[128] = {0}; static char screenshot_file[DIR_MAX]; static int locked_aspect_ratio = 0; static vec4 winbgcolor = {0,0,0,1}; +static float gamma = 2.2f; vec4 window_getcolor_() { return winbgcolor; } // internal @@ -379791,6 +379798,10 @@ int window_frame_begin() { void input_update(); input_update(); + if (gamma) { + postfx_begin(&gamma_fx, window_width(), window_height()); + } + return 1; } @@ -379807,6 +379818,10 @@ void window_frame_end() { glClear(GL_DEPTH_BUFFER_BIT); dd_ontop = 1; ddraw_flush(); + + if (gamma) { + postfx_end(&gamma_fx); + } ui_render(); } @@ -379995,6 +380010,14 @@ void window_color(unsigned color) { unsigned a = (color >> 24) & 255; winbgcolor = vec4(r / 255.0, g / 255.0, b / 255.0, a / 255.0); } +void window_gamma(float _gamma) { + gamma = _gamma; + shader_bind(gamma_fx.pass[postfx_find(&gamma_fx, "fxGamma.fs")].program); + shader_float("gamma", gamma); +} +float window_get_gamma() { + return gamma; +} static int has_icon; int window_has_icon() { return has_icon; @@ -382604,6 +382627,11 @@ static void v4k_post_init(float refresh_rate) { hz = refresh_rate; // t = glfwGetTime(); + do_once { + postfx_load_from_mem(&gamma_fx, "fxGamma.fs", vfs_read("fxGamma.fs")); + postfx_enable(&gamma_fx, 0, 1); + window_gamma(2.2f); + } } // ---------------------------------------------------------------------------- diff --git a/engine/split/v4k_font.c b/engine/split/v4k_font.c index ab16ccc..a9585e4 100644 --- a/engine/split/v4k_font.c +++ b/engine/split/v4k_font.c @@ -1957,6 +1957,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact glUniform1f(glGetUniformLocation(f->program, "scale_factor"), factor); glUniform2fv(glGetUniformLocation(f->program, "string_offset"), 1, &offset.x); glUniform1f(glGetUniformLocation(f->program, "offset_firstline"), f->ascent*f->factor); + glUniform1f(glGetUniformLocation(f->program, "gamma"), (window_get_gamma() + !window_get_gamma())); GLint dims[4] = {0}; glGetIntegerv(GL_VIEWPORT, dims); diff --git a/engine/split/v4k_gui.c b/engine/split/v4k_gui.c index 67fa070..3d16209 100644 --- a/engine/split/v4k_gui.c +++ b/engine/split/v4k_gui.c @@ -6,8 +6,8 @@ API void gui_drawrect( texture_t spritesheet, vec2 tex_start, vec2 tex_end, int #define v42v2(rect) vec2(rect.x,rect.y), vec2(rect.z,rect.w) void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, vec2 start, vec2 end ) { - float gamma = 1; static int program = -1, vbo = -1, vao = -1, u_inv_gamma = -1, u_tint = -1, u_has_tex = -1, u_window_width = -1, u_window_height = -1; + float gamma = window_get_gamma(); vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1)); if( program < 0 ) { const char* vs = vfs_read("shaders/rect_2d.vs"); @@ -34,7 +34,7 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; glUseProgram( program ); - glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + glUniform1f( u_inv_gamma, (gamma + !gamma) ); glBindVertexArray( vao ); diff --git a/engine/split/v4k_main.c b/engine/split/v4k_main.c index 2e36d84..8d6f455 100644 --- a/engine/split/v4k_main.c +++ b/engine/split/v4k_main.c @@ -48,6 +48,11 @@ static void v4k_post_init(float refresh_rate) { hz = refresh_rate; // t = glfwGetTime(); + do_once { + postfx_load_from_mem(&gamma_fx, "fxGamma.fs", vfs_read("fxGamma.fs")); + postfx_enable(&gamma_fx, 0, 1); + window_gamma(2.2f); + } } // ---------------------------------------------------------------------------- diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 7e26b79..8d9a113 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1647,7 +1647,7 @@ skybox_t skybox(const char *asset, int flags) { if( asset ) { int is_panorama = vfs_size( asset ); if( is_panorama ) { // is file - // stbi_hdr_to_ldr_gamma(1.2f); + stbi_hdr_to_ldr_gamma(1.2f); image_t panorama = image( asset, IMAGE_RGBA ); sky.cubemap = cubemap( panorama, 0 ); // RGBA required image_destroy(&panorama); @@ -2376,12 +2376,12 @@ bool postfx_begin(postfx *fx, int width, int height) { fbo_destroy(fx->fb[1]); // create texture, set texture parameters and content - fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[0] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[0] = fbo(fx->diffuse[0].id, fx->depth[0].id, 0); // create texture, set texture parameters and content - fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[1] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[1] = fbo(fx->diffuse[1].id, fx->depth[1].id, 0); } @@ -2484,7 +2484,7 @@ bool postfx_end(postfx *fx) { return true; } -static postfx fx; +static postfx fx, gamma_fx; int fx_load_from_mem(const char *nameid, const char *content) { do_once postfx_create(&fx, 0); return postfx_load_from_mem(&fx, nameid, content); diff --git a/engine/split/v4k_renderdd.c b/engine/split/v4k_renderdd.c index 179c734..2841b5d 100644 --- a/engine/split/v4k_renderdd.c +++ b/engine/split/v4k_renderdd.c @@ -13,8 +13,10 @@ static const char *dd_fs = "//" FILELINE "\n" // "precision mediump float;\n" "in vec3 out_color;\n" "out vec4 fragcolor;\n" + "uniform float gamma; /// set:2.2\n" "void main() {\n" " fragcolor = vec4(out_color, 1.0);\n" + " fragcolor.rgb = pow(fragcolor.rgb, vec3(gamma));\n" "}"; #define X(x) RGBX(x,255) @@ -74,6 +76,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { glUseProgram(dd_program); glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp); + glUniform1f(glGetUniformLocation(dd_program, "gamma"), (window_get_gamma() + !window_get_gamma())); static GLuint vao, vbo; if(!vao) glGenVertexArrays(1, &vao); glBindVertexArray(vao); diff --git a/engine/split/v4k_window.c b/engine/split/v4k_window.c index 4b59b6a..e7f9a3a 100644 --- a/engine/split/v4k_window.c +++ b/engine/split/v4k_window.c @@ -107,6 +107,7 @@ static char title[128] = {0}; static char screenshot_file[DIR_MAX]; static int locked_aspect_ratio = 0; static vec4 winbgcolor = {0,0,0,1}; +static float gamma = 2.2f; vec4 window_getcolor_() { return winbgcolor; } // internal @@ -577,6 +578,10 @@ int window_frame_begin() { void input_update(); input_update(); + if (gamma) { + postfx_begin(&gamma_fx, window_width(), window_height()); + } + return 1; } @@ -593,6 +598,10 @@ void window_frame_end() { glClear(GL_DEPTH_BUFFER_BIT); dd_ontop = 1; ddraw_flush(); + + if (gamma) { + postfx_end(&gamma_fx); + } ui_render(); } @@ -781,6 +790,14 @@ void window_color(unsigned color) { unsigned a = (color >> 24) & 255; winbgcolor = vec4(r / 255.0, g / 255.0, b / 255.0, a / 255.0); } +void window_gamma(float _gamma) { + gamma = _gamma; + shader_bind(gamma_fx.pass[postfx_find(&gamma_fx, "fxGamma.fs")].program); + shader_float("gamma", gamma); +} +float window_get_gamma() { + return gamma; +} static int has_icon; int window_has_icon() { return has_icon; diff --git a/engine/split/v4k_window.h b/engine/split/v4k_window.h index ab96026..254e370 100644 --- a/engine/split/v4k_window.h +++ b/engine/split/v4k_window.h @@ -38,6 +38,8 @@ API void window_loop_exit(); // exit from main loop function (emscripten onl API void window_title(const char *title); API void window_color(unsigned color); +API void window_gamma(float gamma); // 2.2 - standard, 0.0 - disables postfx pass +API float window_get_gamma(); API vec2 window_canvas(); API void* window_handle(); API char* window_stats(); diff --git a/engine/v4k.c b/engine/v4k.c index 0662d08..cc7a08b 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -10659,6 +10659,7 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact glUniform1f(glGetUniformLocation(f->program, "scale_factor"), factor); glUniform2fv(glGetUniformLocation(f->program, "string_offset"), 1, &offset.x); glUniform1f(glGetUniformLocation(f->program, "offset_firstline"), f->ascent*f->factor); + glUniform1f(glGetUniformLocation(f->program, "gamma"), (window_get_gamma() + !window_get_gamma())); GLint dims[4] = {0}; glGetIntegerv(GL_VIEWPORT, dims); @@ -11248,8 +11249,8 @@ API void gui_drawrect( texture_t spritesheet, vec2 tex_start, vec2 tex_end, int #define v42v2(rect) vec2(rect.x,rect.y), vec2(rect.z,rect.w) void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, vec2 start, vec2 end ) { - float gamma = 1; static int program = -1, vbo = -1, vao = -1, u_inv_gamma = -1, u_tint = -1, u_has_tex = -1, u_window_width = -1, u_window_height = -1; + float gamma = window_get_gamma(); vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1)); if( program < 0 ) { const char* vs = vfs_read("shaders/rect_2d.vs"); @@ -11276,7 +11277,7 @@ void gui_drawrect( texture_t texture, vec2 tex_start, vec2 tex_end, int rgba, ve GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; glUseProgram( program ); - glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + glUniform1f( u_inv_gamma, (gamma + !gamma) ); glBindVertexArray( vao ); @@ -18821,7 +18822,7 @@ skybox_t skybox(const char *asset, int flags) { if( asset ) { int is_panorama = vfs_size( asset ); if( is_panorama ) { // is file - // stbi_hdr_to_ldr_gamma(1.2f); + stbi_hdr_to_ldr_gamma(1.2f); image_t panorama = image( asset, IMAGE_RGBA ); sky.cubemap = cubemap( panorama, 0 ); // RGBA required image_destroy(&panorama); @@ -19550,12 +19551,12 @@ bool postfx_begin(postfx *fx, int width, int height) { fbo_destroy(fx->fb[1]); // create texture, set texture parameters and content - fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[0] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[0] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[0] = fbo(fx->diffuse[0].id, fx->depth[0].id, 0); // create texture, set texture parameters and content - fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA); + fx->diffuse[1] = texture_create(width, height, 4, NULL, TEXTURE_RGBA|TEXTURE_FLOAT); fx->depth[1] = texture_create(width, height, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT); fx->fb[1] = fbo(fx->diffuse[1].id, fx->depth[1].id, 0); } @@ -19658,7 +19659,7 @@ bool postfx_end(postfx *fx) { return true; } -static postfx fx; +static postfx fx, gamma_fx; int fx_load_from_mem(const char *nameid, const char *content) { do_once postfx_create(&fx, 0); return postfx_load_from_mem(&fx, nameid, content); @@ -21186,8 +21187,10 @@ static const char *dd_fs = "//" FILELINE "\n" // "precision mediump float;\n" "in vec3 out_color;\n" "out vec4 fragcolor;\n" + "uniform float gamma; /// set:2.2\n" "void main() {\n" " fragcolor = vec4(out_color, 1.0);\n" + " fragcolor.rgb = pow(fragcolor.rgb, vec3(gamma));\n" "}"; #define X(x) RGBX(x,255) @@ -21247,6 +21250,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { glUseProgram(dd_program); glUniformMatrix4fv(glGetUniformLocation(dd_program, "u_MVP"), 1, GL_FALSE, mvp); + glUniform1f(glGetUniformLocation(dd_program, "gamma"), (window_get_gamma() + !window_get_gamma())); static GLuint vao, vbo; if(!vao) glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -26478,6 +26482,7 @@ static char title[128] = {0}; static char screenshot_file[DIR_MAX]; static int locked_aspect_ratio = 0; static vec4 winbgcolor = {0,0,0,1}; +static float gamma = 2.2f; vec4 window_getcolor_() { return winbgcolor; } // internal @@ -26948,6 +26953,10 @@ int window_frame_begin() { void input_update(); input_update(); + if (gamma) { + postfx_begin(&gamma_fx, window_width(), window_height()); + } + return 1; } @@ -26964,6 +26973,10 @@ void window_frame_end() { glClear(GL_DEPTH_BUFFER_BIT); dd_ontop = 1; ddraw_flush(); + + if (gamma) { + postfx_end(&gamma_fx); + } ui_render(); } @@ -27152,6 +27165,14 @@ void window_color(unsigned color) { unsigned a = (color >> 24) & 255; winbgcolor = vec4(r / 255.0, g / 255.0, b / 255.0, a / 255.0); } +void window_gamma(float _gamma) { + gamma = _gamma; + shader_bind(gamma_fx.pass[postfx_find(&gamma_fx, "fxGamma.fs")].program); + shader_float("gamma", gamma); +} +float window_get_gamma() { + return gamma; +} static int has_icon; int window_has_icon() { return has_icon; @@ -29761,6 +29782,11 @@ static void v4k_post_init(float refresh_rate) { hz = refresh_rate; // t = glfwGetTime(); + do_once { + postfx_load_from_mem(&gamma_fx, "fxGamma.fs", vfs_read("fxGamma.fs")); + postfx_enable(&gamma_fx, 0, 1); + window_gamma(2.2f); + } } // ---------------------------------------------------------------------------- diff --git a/engine/v4k.h b/engine/v4k.h index e7b1574..1f3bd56 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -4755,6 +4755,8 @@ API void window_loop_exit(); // exit from main loop function (emscripten onl API void window_title(const char *title); API void window_color(unsigned color); +API void window_gamma(float gamma); // 2.2 - standard, 0.0 - disables postfx pass +API float window_get_gamma(); API vec2 window_canvas(); API void* window_handle(); API char* window_stats();