From 6e1fe4ddd9209aa1b5bc562d92f82a6bfb743513 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 9 Oct 2013 15:57:32 +0000 Subject: Implementation of curve mapping in GLSL The title says it all, now having curve mapping enabled in color management settings wouldn't force fallback from GLSL to CPU based color space conversion. --- .../opencolorio/gpu_shader_display_transform.glsl | 123 +++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 intern/opencolorio/gpu_shader_display_transform.glsl (limited to 'intern/opencolorio/gpu_shader_display_transform.glsl') diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl new file mode 100644 index 00000000000..6ba3fa55e8f --- /dev/null +++ b/intern/opencolorio/gpu_shader_display_transform.glsl @@ -0,0 +1,123 @@ +uniform sampler2D image_texture; +uniform sampler3D lut3d_texture; +uniform bool predivide; + +#ifdef USE_CURVE_MAPPING +/* Curve mapping parameters + * + * See documentation for OCIO_CurveMappingSettings to get fields descriptions. + * (this ones pretyt much copies stuff from C structure.) + */ +uniform sampler1D curve_mapping_texture; +uniform int curve_mapping_lut_size; +uniform ivec4 use_curve_mapping_extend_extrapolate; +uniform vec4 curve_mapping_mintable; +uniform vec4 curve_mapping_range; +uniform vec4 curve_mapping_ext_in_x; +uniform vec4 curve_mapping_ext_in_y; +uniform vec4 curve_mapping_ext_out_x; +uniform vec4 curve_mapping_ext_out_y; +uniform vec4 curve_mapping_first_x; +uniform vec4 curve_mapping_first_y; +uniform vec4 curve_mapping_last_x; +uniform vec4 curve_mapping_last_y; +uniform vec3 curve_mapping_black; +uniform vec3 curve_mapping_bwmul; + +float read_curve_mapping(int table, int index) +{ + /* TODO(sergey): Without -1 here image is getting darken after applying unite curve. + * But is it actually correct to subtract 1 here? + */ + float texture_index = float(index) / float(curve_mapping_lut_size - 1); + return texture1D(curve_mapping_texture, texture_index) [table]; +} + +float curvemap_calc_extend(int table, float x, vec2 first, vec2 last) +{ + if (x <= first[0]) { + if (use_curve_mapping_extend_extrapolate[table] == 0) { + /* no extrapolate */ + return first[1]; + } + else { + if (curve_mapping_ext_in_x[table] == 0.0) + return first[1] + curve_mapping_ext_in_y[table] * 10000.0; + else + return first[1] + curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table]; + } + } + else if (x >= last[0]) { + if (use_curve_mapping_extend_extrapolate[table] == 0) { + /* no extrapolate */ + return last[1]; + } + else { + if (curve_mapping_ext_out_x[table] == 0.0) + return last[1] - curve_mapping_ext_out_y[table] * 10000.0; + else + return last[1] + curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table]; + } + } + return 0.0; +} + +float curvemap_evaluateF(int table, float value) +{ + float mintable_ = curve_mapping_mintable[table]; + float range = curve_mapping_range[table]; + float mintable = 0.0; + int CM_TABLE = curve_mapping_lut_size - 1; + + float fi; + int i; + + /* index in table */ + fi = (value - mintable) * range; + i = int(fi); + + /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */ + if (fi < 0.0 || fi > float(CM_TABLE)) { + return curvemap_calc_extend(table, value, + vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]), + vec2(curve_mapping_last_x[table], curve_mapping_last_y[table])); + } + else { + if (i < 0) return read_curve_mapping(table, 0); + if (i >= CM_TABLE) return read_curve_mapping(table, CM_TABLE); + + fi = fi - float(i); + return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1); + } +} + +vec4 curvemapping_evaluate_premulRGBF(vec4 col) +{ + vec4 result = col; + result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]); + result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]); + result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]); + result[3] = col[3]; + return result; +} +#endif + +void main() +{ + vec4 col = texture2D(image_texture, gl_TexCoord[0].st); +#ifdef USE_CURVE_MAPPING + col = curvemapping_evaluate_premulRGBF(col); +#endif + if (predivide && col[3] > 0.0 && col[3] < 1.0) { + float inv_alpha = 1.0 / col[3]; + col[0] *= inv_alpha; + col[1] *= inv_alpha; + col[2] *= inv_alpha; + } + + /* NOTE: This is true we only do de-premul here and NO premul + * and the reason is simple -- opengl is always configured + * for straight alpha at this moment + */ + gl_FragColor = OCIODisplay(col, lut3d_texture); +} -- cgit v1.2.3