forked from bartvdbraak/blender
ColorRamp HSV, HSL Blend Modes
D297 by charlie with own edits
This commit is contained in:
parent
36cbdb860a
commit
2b796ed03d
@ -41,6 +41,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_kdopbvh.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_math_color.h"
|
||||
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@ -237,7 +238,7 @@ void init_colorband(ColorBand *coba, bool rangetype)
|
||||
}
|
||||
|
||||
coba->tot = 2;
|
||||
|
||||
coba->color_mode = COLBAND_BLEND_RGB;
|
||||
}
|
||||
|
||||
ColorBand *add_colorband(bool rangetype)
|
||||
@ -252,106 +253,219 @@ ColorBand *add_colorband(bool rangetype)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static float colorband_hue_interp(
|
||||
const int ipotype_hue,
|
||||
const float mfac, const float fac,
|
||||
float h1, float h2)
|
||||
{
|
||||
float h_interp;
|
||||
int mode = 0;
|
||||
|
||||
#define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b)))
|
||||
#define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h) - 1.0f)
|
||||
|
||||
h1 = HUE_MOD(h1);
|
||||
h2 = HUE_MOD(h2);
|
||||
|
||||
BLI_assert(h1 >= 0.0f && h1 < 1.0f);
|
||||
BLI_assert(h2 >= 0.0f && h2 < 1.0f);
|
||||
|
||||
switch (ipotype_hue) {
|
||||
case COLBAND_HUE_NEAR:
|
||||
{
|
||||
if ((h1 < h2) && (h2 - h1) > +0.5f) mode = 1;
|
||||
else if ((h1 > h2) && (h2 - h1) < -0.5f) mode = 2;
|
||||
else mode = 0;
|
||||
break;
|
||||
}
|
||||
case COLBAND_HUE_FAR:
|
||||
{
|
||||
if ((h1 < h2) && (h2 - h1) < +0.5f) mode = 1;
|
||||
else if ((h1 > h2) && (h2 - h1) > -0.5f) mode = 2;
|
||||
else mode = 0;
|
||||
break;
|
||||
}
|
||||
case COLBAND_HUE_CW:
|
||||
{
|
||||
if (h1 > h2) mode = 2;
|
||||
else mode = 0;
|
||||
break;
|
||||
}
|
||||
case COLBAND_HUE_CCW:
|
||||
{
|
||||
if (h1 < h2) mode = 1;
|
||||
else mode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
h_interp = HUE_INTERP(h1, h2);
|
||||
break;
|
||||
case 1:
|
||||
h_interp = HUE_INTERP(h1 + 1.0f, h2);
|
||||
h_interp = HUE_MOD(h_interp);
|
||||
break;
|
||||
case 2:
|
||||
h_interp = HUE_INTERP(h1, h2 + 1.0f);
|
||||
h_interp = HUE_MOD(h_interp);
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_assert(h_interp >= 0.0f && h_interp < 1.0f);
|
||||
|
||||
#undef HUE_INTERP
|
||||
#undef HUE_MOD
|
||||
|
||||
return h_interp;
|
||||
}
|
||||
|
||||
bool do_colorband(const ColorBand *coba, float in, float out[4])
|
||||
{
|
||||
const CBData *cbd1, *cbd2, *cbd0, *cbd3;
|
||||
float fac, mfac, t[4];
|
||||
float fac;
|
||||
int ipotype;
|
||||
int a;
|
||||
|
||||
if (coba == NULL || coba->tot == 0) return 0;
|
||||
|
||||
cbd1 = coba->data;
|
||||
|
||||
ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR;
|
||||
|
||||
if (coba->tot == 1) {
|
||||
out[0] = cbd1->r;
|
||||
out[1] = cbd1->g;
|
||||
out[2] = cbd1->b;
|
||||
out[3] = cbd1->a;
|
||||
}
|
||||
else if ((in <= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
|
||||
out[0] = cbd1->r;
|
||||
out[1] = cbd1->g;
|
||||
out[2] = cbd1->b;
|
||||
out[3] = cbd1->a;
|
||||
}
|
||||
else {
|
||||
if (in <= cbd1->pos && coba->ipotype < 2) {
|
||||
CBData left, right;
|
||||
|
||||
/* we're looking for first pos > in */
|
||||
for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
|
||||
|
||||
if (a == coba->tot) {
|
||||
cbd2 = cbd1 - 1;
|
||||
right = *cbd2;
|
||||
right.pos = 1.0f;
|
||||
cbd1 = &right;
|
||||
}
|
||||
else if (a == 0) {
|
||||
left = *cbd1;
|
||||
left.pos = 0.0f;
|
||||
cbd2 = &left;
|
||||
}
|
||||
else {
|
||||
cbd2 = cbd1 - 1;
|
||||
}
|
||||
|
||||
if ((in >= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
|
||||
out[0] = cbd1->r;
|
||||
out[1] = cbd1->g;
|
||||
out[2] = cbd1->b;
|
||||
out[3] = cbd1->a;
|
||||
}
|
||||
else {
|
||||
CBData left, right;
|
||||
|
||||
/* we're looking for first pos > in */
|
||||
for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
|
||||
|
||||
if (a == coba->tot) {
|
||||
cbd2 = cbd1 - 1;
|
||||
right = *cbd2;
|
||||
right.pos = 1.0f;
|
||||
cbd1 = &right;
|
||||
}
|
||||
else if (a == 0) {
|
||||
left = *cbd1;
|
||||
left.pos = 0.0f;
|
||||
cbd2 = &left;
|
||||
}
|
||||
else {
|
||||
cbd2 = cbd1 - 1;
|
||||
}
|
||||
|
||||
if (in >= cbd1->pos && coba->ipotype < 2) {
|
||||
out[0] = cbd1->r;
|
||||
out[1] = cbd1->g;
|
||||
out[2] = cbd1->b;
|
||||
out[3] = cbd1->a;
|
||||
}
|
||||
else {
|
||||
|
||||
if (cbd2->pos != cbd1->pos)
|
||||
fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
|
||||
else {
|
||||
/* was setting to 0.0 in 2.56 & previous, but this
|
||||
* is incorrect for the last element, see [#26732] */
|
||||
fac = (a != coba->tot) ? 0.0f : 1.0f;
|
||||
}
|
||||
|
||||
if (coba->ipotype == 4) {
|
||||
/* constant */
|
||||
out[0] = cbd2->r;
|
||||
out[1] = cbd2->g;
|
||||
out[2] = cbd2->b;
|
||||
out[3] = cbd2->a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (coba->ipotype >= 2) {
|
||||
/* ipo from right to left: 3 2 1 0 */
|
||||
|
||||
if (a >= coba->tot - 1) cbd0 = cbd1;
|
||||
else cbd0 = cbd1 + 1;
|
||||
if (a < 2) cbd3 = cbd2;
|
||||
else cbd3 = cbd2 - 1;
|
||||
|
||||
CLAMP(fac, 0.0f, 1.0f);
|
||||
|
||||
if (coba->ipotype == 3)
|
||||
key_curve_position_weights(fac, t, KEY_CARDINAL);
|
||||
else
|
||||
key_curve_position_weights(fac, t, KEY_BSPLINE);
|
||||
|
||||
out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
|
||||
out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
|
||||
out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
|
||||
out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
|
||||
CLAMP(out[0], 0.0f, 1.0f);
|
||||
CLAMP(out[1], 0.0f, 1.0f);
|
||||
CLAMP(out[2], 0.0f, 1.0f);
|
||||
CLAMP(out[3], 0.0f, 1.0f);
|
||||
if (cbd2->pos != cbd1->pos) {
|
||||
fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
|
||||
}
|
||||
else {
|
||||
/* was setting to 0.0 in 2.56 & previous, but this
|
||||
* is incorrect for the last element, see [#26732] */
|
||||
fac = (a != coba->tot) ? 0.0f : 1.0f;
|
||||
}
|
||||
|
||||
if (coba->ipotype == COLBAND_INTERP_CONSTANT) {
|
||||
/* constant */
|
||||
out[0] = cbd2->r;
|
||||
out[1] = cbd2->g;
|
||||
out[2] = cbd2->b;
|
||||
out[3] = cbd2->a;
|
||||
}
|
||||
else if (ipotype >= COLBAND_INTERP_B_SPLINE) {
|
||||
/* ipo from right to left: 3 2 1 0 */
|
||||
float t[4];
|
||||
|
||||
if (a >= coba->tot - 1) cbd0 = cbd1;
|
||||
else cbd0 = cbd1 + 1;
|
||||
if (a < 2) cbd3 = cbd2;
|
||||
else cbd3 = cbd2 - 1;
|
||||
|
||||
CLAMP(fac, 0.0f, 1.0f);
|
||||
|
||||
if (ipotype == COLBAND_INTERP_CARDINAL) {
|
||||
key_curve_position_weights(fac, t, KEY_CARDINAL);
|
||||
}
|
||||
else {
|
||||
|
||||
if (coba->ipotype == 1) { /* EASE */
|
||||
mfac = fac * fac;
|
||||
fac = 3.0f * mfac - 2.0f * mfac * fac;
|
||||
}
|
||||
mfac = 1.0f - fac;
|
||||
|
||||
key_curve_position_weights(fac, t, KEY_BSPLINE);
|
||||
}
|
||||
|
||||
out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
|
||||
out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
|
||||
out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
|
||||
out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
|
||||
CLAMP(out[0], 0.0f, 1.0f);
|
||||
CLAMP(out[1], 0.0f, 1.0f);
|
||||
CLAMP(out[2], 0.0f, 1.0f);
|
||||
CLAMP(out[3], 0.0f, 1.0f);
|
||||
}
|
||||
else {
|
||||
float mfac;
|
||||
|
||||
if (ipotype == COLBAND_INTERP_EASE) {
|
||||
mfac = fac * fac;
|
||||
fac = 3.0f * mfac - 2.0f * mfac * fac;
|
||||
}
|
||||
|
||||
mfac = 1.0f - fac;
|
||||
|
||||
if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) {
|
||||
float col1[3], col2[3];
|
||||
|
||||
linearrgb_to_srgb_v3_v3(col1, &cbd1->r);
|
||||
linearrgb_to_srgb_v3_v3(col2, &cbd2->r);
|
||||
|
||||
rgb_to_hsv_v(col1, col1);
|
||||
rgb_to_hsv_v(col2, col2);
|
||||
|
||||
out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
|
||||
out[1] = mfac * col1[1] + fac * col2[1];
|
||||
out[2] = mfac * col1[2] + fac * col2[2];
|
||||
out[3] = mfac * cbd1->a + fac * cbd2->a;
|
||||
|
||||
hsv_to_rgb_v(out, out);
|
||||
|
||||
srgb_to_linearrgb_v3_v3(out, out);
|
||||
}
|
||||
else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) {
|
||||
float col1[3], col2[3];
|
||||
|
||||
linearrgb_to_srgb_v3_v3(col1, &cbd1->r);
|
||||
linearrgb_to_srgb_v3_v3(col2, &cbd2->r);
|
||||
|
||||
rgb_to_hsl_v(col1, col1);
|
||||
rgb_to_hsl_v(col2, col2);
|
||||
|
||||
out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
|
||||
out[1] = mfac * col1[1] + fac * col2[1];
|
||||
out[2] = mfac * col1[2] + fac * col2[2];
|
||||
out[3] = mfac * cbd1->a + fac * cbd2->a;
|
||||
|
||||
hsl_to_rgb_v(out, out);
|
||||
|
||||
srgb_to_linearrgb_v3_v3(out, out);
|
||||
}
|
||||
else {
|
||||
/* COLBAND_BLEND_RGB */
|
||||
out[0] = mfac * cbd1->r + fac * cbd2->r;
|
||||
out[1] = mfac * cbd1->g + fac * cbd2->g;
|
||||
out[2] = mfac * cbd1->b + fac * cbd2->b;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string.h"
|
||||
@ -1529,7 +1530,15 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
|
||||
|
||||
row = uiLayoutRow(split, false);
|
||||
|
||||
uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
|
||||
uiBlockBeginAlign(block);
|
||||
uiItemR(row, &ptr, "color_mode", 0, "", ICON_NONE);
|
||||
if (ELEM(coba->color_mode, COLBAND_BLEND_HSV, COLBAND_BLEND_HSL)) {
|
||||
uiItemR(row, &ptr, "hue_interpolation", 0, "", ICON_NONE);
|
||||
}
|
||||
else { /* COLBAND_BLEND_RGB */
|
||||
uiItemR(row, &ptr, "interpolation", 0, "", ICON_NONE);
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
row = uiLayoutRow(layout, false);
|
||||
|
||||
@ -1567,7 +1576,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand
|
||||
uiDefButS(block, NUM, 0, "", 0, 0, 5.0f * UI_UNIT_X, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)),
|
||||
0, 0, TIP_("Choose active color stop"));
|
||||
row = uiLayoutRow(subsplit, false);
|
||||
uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
|
||||
uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
|
||||
bt = block->buttons.last;
|
||||
uiButSetFunc(bt, colorband_update_cb, bt, coba);
|
||||
|
||||
|
@ -111,9 +111,12 @@ typedef struct CBData {
|
||||
/* 32 = MAXCOLORBAND */
|
||||
/* note that this has to remain a single struct, for UserDef */
|
||||
typedef struct ColorBand {
|
||||
short flag, tot, cur, ipotype;
|
||||
short tot, cur;
|
||||
char ipotype, ipotype_hue;
|
||||
char color_mode;
|
||||
char pad[1];
|
||||
|
||||
CBData data[32];
|
||||
|
||||
} ColorBand;
|
||||
|
||||
typedef struct EnvMap {
|
||||
@ -510,6 +513,32 @@ typedef struct ColorMapping {
|
||||
#define MTEX_MAP_MODE_RANDOM 4
|
||||
#define MTEX_MAP_MODE_STENCIL 5
|
||||
|
||||
/* **************** ColorBand ********************* */
|
||||
|
||||
/* colormode */
|
||||
enum {
|
||||
COLBAND_BLEND_RGB = 0,
|
||||
COLBAND_BLEND_HSV = 1,
|
||||
COLBAND_BLEND_HSL = 2,
|
||||
};
|
||||
|
||||
/* interpolation */
|
||||
enum {
|
||||
COLBAND_INTERP_LINEAR = 0,
|
||||
COLBAND_INTERP_EASE = 1,
|
||||
COLBAND_INTERP_B_SPLINE = 2,
|
||||
COLBAND_INTERP_CARDINAL = 3,
|
||||
COLBAND_INTERP_CONSTANT = 4,
|
||||
};
|
||||
|
||||
/* color interpolation */
|
||||
enum {
|
||||
COLBAND_HUE_NEAR = 0,
|
||||
COLBAND_HUE_FAR = 1,
|
||||
COLBAND_HUE_CW = 2,
|
||||
COLBAND_HUE_CCW = 3,
|
||||
};
|
||||
|
||||
/* **************** EnvMap ********************* */
|
||||
|
||||
/* type */
|
||||
|
@ -850,7 +850,12 @@ static void rna_def_color_ramp_element(BlenderRNA *brna)
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_ui_text(prop, "Color", "Set color of selected color stop");
|
||||
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "a");
|
||||
RNA_def_property_ui_text(prop, "Alpha", "Set alpha of selected color stop");
|
||||
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "position", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "pos");
|
||||
RNA_def_property_range(prop, 0, 1);
|
||||
@ -895,14 +900,29 @@ static void rna_def_color_ramp(BlenderRNA *brna)
|
||||
FunctionRNA *func;
|
||||
|
||||
static EnumPropertyItem prop_interpolation_items[] = {
|
||||
{1, "EASE", 0, "Ease", ""},
|
||||
{3, "CARDINAL", 0, "Cardinal", ""},
|
||||
{0, "LINEAR", 0, "Linear", ""},
|
||||
{2, "B_SPLINE", 0, "B-Spline", ""},
|
||||
{4, "CONSTANT", 0, "Constant", ""},
|
||||
{COLBAND_INTERP_EASE, "EASE", 0, "Ease", ""},
|
||||
{COLBAND_INTERP_CARDINAL, "CARDINAL", 0, "Cardinal", ""},
|
||||
{COLBAND_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
|
||||
{COLBAND_INTERP_B_SPLINE, "B_SPLINE", 0, "B-Spline", ""},
|
||||
{COLBAND_INTERP_CONSTANT, "CONSTANT", 0, "Constant", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem prop_mode_items[] = {
|
||||
{COLBAND_BLEND_RGB, "RGB", 0, "RGB", ""},
|
||||
{COLBAND_BLEND_HSV, "HSV", 0, "HSV", ""},
|
||||
{COLBAND_BLEND_HSL, "HSL", 0, "HSL", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem prop_hsv_items[] = {
|
||||
{COLBAND_HUE_NEAR, "NEAR", 0, "Near", ""},
|
||||
{COLBAND_HUE_FAR, "FAR", 0, "Far", ""},
|
||||
{COLBAND_HUE_CW, "CW", 0, "Clockwise", ""},
|
||||
{COLBAND_HUE_CCW, "CCW", 0, "Counter-Clockwise", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "ColorRamp", NULL);
|
||||
RNA_def_struct_sdna(srna, "ColorBand");
|
||||
RNA_def_struct_path_func(srna, "rna_ColorRamp_path");
|
||||
@ -921,6 +941,18 @@ static void rna_def_color_ramp(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Interpolation", "Set interpolation between color stops");
|
||||
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "hue_interpolation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "ipotype_hue");
|
||||
RNA_def_property_enum_items(prop, prop_hsv_items);
|
||||
RNA_def_property_ui_text(prop, "Color Interpolation", "Set color interpolation");
|
||||
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "color_mode");
|
||||
RNA_def_property_enum_items(prop, prop_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Color Mode", "Set color mode to use for interpolation");
|
||||
RNA_def_property_update(prop, 0, "rna_ColorRamp_update");
|
||||
|
||||
#if 0 /* use len(elements) */
|
||||
prop = RNA_def_property(srna, "total", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tot");
|
||||
|
Loading…
Reference in New Issue
Block a user