blender/intern/cycles/kernel/shaders/node_rgb_curves.osl
Sergey Sharybin ed5dbb0a7b Cycles: Implement extrapolation for RGB curves
Previously RGB Curves node will clamp input to 0..1 which is rather useless
when one wants to use HDR image textures and do bit of correction on them.

Now kernel code supports extrapolation of baked LUT based on first/last two
table points and performs linear extrapolation.

The only tricky part is to guess the range to bake the LUT for. Currently
it's using simple approach -- minmax of the input curves. While this behaves
ok for the simple cases it's easy to trick the system up causing incorrect
results.

Not sure we can solve those issues in a general case and since the new code
is giving more expected results it's not that bad actually. In the worst
case artist migh always create explicit point to make sure LUT is created
for the needed HDR range.

Reviewers: brecht, juicyfruit

Subscribers: sebastian_k

Differential Revision: https://developer.blender.org/D1658
2015-12-06 01:21:14 +05:00

71 lines
1.8 KiB
Plaintext

/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stdosl.h"
#include "oslutil.h"
float ramp_lookup(color ramp[RAMP_TABLE_SIZE], float at, int component)
{
if (at < 0.0 || at > 1.0) {
float t0, dy;
if(at < 0.0) {
t0 = ramp[0][component];
dy = t0 - ramp[1][component];
at = -at;
}
else {
t0 = ramp[RAMP_TABLE_SIZE - 1][component];
dy = t0 - ramp[RAMP_TABLE_SIZE - 2][component];
at = at - 1.0;
}
return t0 + dy * at * (RAMP_TABLE_SIZE - 1);
}
float f = clamp(at, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1);
/* clamp int as well in case of NaN */
int i = (int)f;
if (i < 0) i = 0;
if (i >= RAMP_TABLE_SIZE) i = RAMP_TABLE_SIZE - 1;
float t = f - (float)i;
float result = ramp[i][component];
if (t > 0.0)
result = (1.0 - t) * result + t * ramp[i + 1][component];
return result;
}
shader node_rgb_curves(
color ramp[RAMP_TABLE_SIZE] = {0.0},
float min_x = 0.0,
float max_x = 1.0,
color ColorIn = 0.0,
float Fac = 0.0,
output color ColorOut = 0.0)
{
color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
ColorOut[0] = ramp_lookup(ramp, c[0], 0);
ColorOut[1] = ramp_lookup(ramp, c[1], 1);
ColorOut[2] = ramp_lookup(ramp, c[2], 2);
ColorOut = mix(ColorIn, ColorOut, Fac);
}