From e1a62fa1a61167990c4ade74b9e8b56573e18d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 6 Mar 2019 23:53:35 +0100 Subject: Fix T62259: RGB Curves behave differently in Cycles and Eevee This was due to curve being not extrapolated correctly. Also curvemap range was not taken into account. --- .../blender/gpu/shaders/gpu_shader_material.glsl | 51 ++++++++++++++++++---- .../nodes/shader/nodes/node_shader_curves.c | 34 +++++++++++++-- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index a7231bda263..422487d075d 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -479,16 +479,49 @@ void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out v outvec = mix(vec, outvec, fac); } -void curves_rgb(float fac, vec4 col, sampler1DArray curvemap, float layer, out vec4 outcol) -{ - vec4 co = vec4(col.rgb, layer); - co.x = texture(curvemap, co.xw).a; - co.y = texture(curvemap, co.yw).a; - co.z = texture(curvemap, co.zw).a; - outcol.r = texture(curvemap, co.xw).r; - outcol.g = texture(curvemap, co.yw).g; - outcol.b = texture(curvemap, co.zw).b; +/* ext is vec4(in_x, in_dy, out_x, out_dy). */ +float curve_extrapolate(float x, float y, vec4 ext) +{ + if (x < 0.0) { + return y + x * ext.y; + } + else if (x > 1.0) { + return y + (x - 1.0) * ext.w; + } + else { + return y; + } +} + +#define RANGE_RESCALE(x, min, range) ((x - min) * range) + +void curves_rgb( + float fac, vec4 col, sampler1DArray curvemap, float layer, + vec4 range, vec4 ext_r, vec4 ext_g, vec4 ext_b, vec4 ext_a, + out vec4 outcol) +{ + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; + + samp.r = curve_extrapolate(co.x, samp.r, ext_a); + samp.g = curve_extrapolate(co.y, samp.g, ext_a); + samp.b = curve_extrapolate(co.z, samp.b, ext_a); + + vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); + co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); + + samp.r = texture(curvemap, co.xw).r; + samp.g = texture(curvemap, co.yw).g; + samp.b = texture(curvemap, co.zw).b; + + outcol.r = curve_extrapolate(co.x, samp.r, ext_r); + outcol.g = curve_extrapolate(co.y, samp.g, ext_g); + outcol.b = curve_extrapolate(co.z, samp.b, ext_b); outcol.a = col.a; + outcol = mix(col, outcol, fac); } diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index 4b89f8d26f8..e4c37636347 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -116,11 +116,39 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UN float *array, layer; int size; - curvemapping_initialize(node->storage); - curvemapping_table_RGBA(node->storage, &array, &size); + CurveMapping *cumap = node->storage; + + curvemapping_initialize(cumap); + curvemapping_table_RGBA(cumap, &array, &size); GPUNodeLink *tex = GPU_color_band(mat, size, array, &layer); - return GPU_stack_link(mat, node, "curves_rgb", in, out, tex, GPU_constant(&layer)); + float ext_rgba[4][4]; + float range_rgba[4]; + + for (int a = 0; a < CM_TOT; ++a) { + const CurveMap *cm = &cumap->cm[a]; + ext_rgba[a][0] = cm->mintable; + ext_rgba[a][2] = cm->maxtable; + range_rgba[a] = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable); + /* Compute extrapolation gradients. */ + if ((cm->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { + ext_rgba[a][1] = (cm->ext_in[0] != 0.0f) ? (cm->ext_in[1] / (cm->ext_in[0] * range_rgba[a])) : 1e8f; + ext_rgba[a][3] = (cm->ext_out[0] != 0.0f) ? (cm->ext_out[1] / (cm->ext_out[0] * range_rgba[a])) : 1e8f; + } + else { + ext_rgba[a][1] = 0.0f; + ext_rgba[a][3] = 0.0f; + } + print_v4_id(ext_rgba[a]); + } + + return GPU_stack_link(mat, node, "curves_rgb", in, out, tex, + GPU_constant(&layer), + GPU_uniform(range_rgba), + GPU_uniform(ext_rgba[0]), + GPU_uniform(ext_rgba[1]), + GPU_uniform(ext_rgba[2]), + GPU_uniform(ext_rgba[3])); } void register_node_type_sh_curve_rgb(void) -- cgit v1.2.3