Fix T38773: Inconsistent conversion of colors and float values in

Blender Internal shader nodes.

All nodes now use the `nodestack_get_vec` function to convert whatever
input values are connected to the desired type, instead of using the
stack values directly regardless of what they contain.

Note that this might break old node setups that have been adapted to the
faulty behavior, but as discussed in the bug report the 2.70 version is
the right time to fix this.
This commit is contained in:
Lukas Tönne 2014-02-25 10:11:48 +01:00
parent bf547a1983
commit 3ae641eb02
Notes: blender-bot 2023-06-07 10:31:13 +02:00
Referenced by issue #38773, Blender Internal: Inverting alpha looks odd in material node setting.
Referenced by issue #38773, Blender Internal: Inverting alpha looks odd in material node setting.
7 changed files with 119 additions and 88 deletions

View File

@ -101,13 +101,15 @@ static bNodeSocketTemplate sh_node_curve_rgb_out[] = {
static void node_shader_exec_curve_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
float fac;
/* stack order input: vec */
/* stack order output: vec */
nodestack_get_vec(&fac, SOCK_FLOAT, in[0]);
nodestack_get_vec(vec, SOCK_VECTOR, in[1]);
curvemapping_evaluateRGBF(node->storage, out[0]->vec, vec);
if (in[0]->vec[0] != 1.0f) {
interp_v3_v3v3(out[0]->vec, vec, out[0]->vec, *in[0]->vec);
if (fac != 1.0f) {
interp_v3_v3v3(out[0]->vec, vec, out[0]->vec, fac);
}
}

View File

@ -48,21 +48,21 @@ static bNodeSocketTemplate sh_node_hue_sat_out[] = {
};
/* note: it would be possible to use CMP version for both nodes */
static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *sat, float *val, float *in, float *fac)
static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float hue, float sat, float val, float in[4], float fac)
{
if (*fac != 0.0f && (*hue != 0.5f || *sat != 1.0f || *val != 1.0f)) {
float col[3], hsv[3], mfac = 1.0f - *fac;
if (fac != 0.0f && (hue != 0.5f || sat != 1.0f || val != 1.0f)) {
float col[3], hsv[3], mfac = 1.0f - fac;
rgb_to_hsv(in[0], in[1], in[2], hsv, hsv + 1, hsv + 2);
hsv[0] += (*hue - 0.5f);
hsv[0] += (hue - 0.5f);
if (hsv[0] > 1.0f) hsv[0] -= 1.0f; else if (hsv[0] < 0.0f) hsv[0] += 1.0f;
hsv[1] *= *sat;
hsv[2] *= *val;
hsv[1] *= sat;
hsv[2] *= val;
hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col + 1, col + 2);
out[0] = mfac * in[0] + *fac * col[0];
out[1] = mfac * in[1] + *fac * col[1];
out[2] = mfac * in[2] + *fac * col[2];
out[0] = mfac * in[0] + fac * col[0];
out[1] = mfac * in[1] + fac * col[1];
out[2] = mfac * in[2] + fac * col[2];
}
else {
copy_v4_v4(out, in);
@ -70,8 +70,15 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *s
}
static void node_shader_exec_hue_sat(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec);
{
float hue, sat, val, fac;
float col[4];
nodestack_get_vec(&hue, SOCK_FLOAT, in[0]);
nodestack_get_vec(&sat, SOCK_FLOAT, in[1]);
nodestack_get_vec(&val, SOCK_FLOAT, in[2]);
nodestack_get_vec(&fac, SOCK_FLOAT, in[3]);
nodestack_get_vec(col, SOCK_RGBA, in[4]);
do_hue_sat_fac(node, out[0]->vec, hue, sat, val, col, fac);
}

View File

@ -49,22 +49,20 @@ static bNodeSocketTemplate sh_node_invert_out[] = {
static void node_shader_exec_invert(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in,
bNodeStack **out)
{
float col[3], facm;
float col[3], icol[3], fac;
col[0] = 1.0f - in[1]->vec[0];
col[1] = 1.0f - in[1]->vec[1];
col[2] = 1.0f - in[1]->vec[2];
nodestack_get_vec(&fac, SOCK_FLOAT, in[0]);
nodestack_get_vec(col, SOCK_VECTOR, in[1]);
icol[0] = 1.0f - col[0];
icol[1] = 1.0f - col[1];
icol[2] = 1.0f - col[2];
/* if fac, blend result against original input */
if (in[0]->vec[0] < 1.0f) {
facm = 1.0f - in[0]->vec[0];
col[0] = in[0]->vec[0] * col[0] + (facm * in[1]->vec[0]);
col[1] = in[0]->vec[0] * col[1] + (facm * in[1]->vec[1]);
col[2] = in[0]->vec[0] * col[2] + (facm * in[1]->vec[2]);
}
copy_v3_v3(out[0]->vec, col);
if (fac < 1.0f)
interp_v3_v3v3(out[0]->vec, col, icol, fac);
else
copy_v3_v3(out[0]->vec, icol);
}
static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)

View File

@ -47,64 +47,69 @@ static bNodeSocketTemplate sh_node_math_out[] = {
static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float a, b, r = 0.0f;
nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
switch (node->custom1) {
case 0: /* Add */
out[0]->vec[0] = in[0]->vec[0] + in[1]->vec[0];
r = a + b;
break;
case 1: /* Subtract */
out[0]->vec[0] = in[0]->vec[0] - in[1]->vec[0];
r = a - b;
break;
case 2: /* Multiply */
out[0]->vec[0] = in[0]->vec[0] * in[1]->vec[0];
r = a * b;
break;
case 3: /* Divide */
{
if (in[1]->vec[0] == 0) /* We don't want to divide by zero. */
out[0]->vec[0] = 0.0;
if (b == 0) /* We don't want to divide by zero. */
r = 0.0;
else
out[0]->vec[0] = in[0]->vec[0] / in[1]->vec[0];
r = a / b;
break;
}
case 4: /* Sine */
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
out[0]->vec[0] = sin(in[0]->vec[0]);
r = sin(a);
else
out[0]->vec[0] = sin(in[1]->vec[0]);
r = sin(b);
break;
}
case 5: /* Cosine */
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
out[0]->vec[0] = cos(in[0]->vec[0]);
r = cos(a);
else
out[0]->vec[0] = cos(in[1]->vec[0]);
r = cos(b);
break;
}
case 6: /* Tangent */
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
out[0]->vec[0] = tan(in[0]->vec[0]);
r = tan(a);
else
out[0]->vec[0] = tan(in[1]->vec[0]);
r = tan(b);
break;
}
case 7: /* Arc-Sine */
{
if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
/* Can't do the impossible... */
if (in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1)
out[0]->vec[0] = asin(in[0]->vec[0]);
if (a <= 1 && a >= -1)
r = asin(a);
else
out[0]->vec[0] = 0.0;
r = 0.0;
}
else {
/* Can't do the impossible... */
if (in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1)
out[0]->vec[0] = asin(in[1]->vec[0]);
if (b <= 1 && b >= -1)
r = asin(b);
else
out[0]->vec[0] = 0.0;
r = 0.0;
}
break;
}
@ -112,43 +117,43 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
{
if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
/* Can't do the impossible... */
if (in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1)
out[0]->vec[0] = acos(in[0]->vec[0]);
if (a <= 1 && a >= -1)
r = acos(a);
else
out[0]->vec[0] = 0.0;
r = 0.0;
}
else {
/* Can't do the impossible... */
if (in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1)
out[0]->vec[0] = acos(in[1]->vec[0]);
if (b <= 1 && b >= -1)
r = acos(b);
else
out[0]->vec[0] = 0.0;
r = 0.0;
}
break;
}
case 9: /* Arc-Tangent */
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
out[0]->vec[0] = atan(in[0]->vec[0]);
r = atan(a);
else
out[0]->vec[0] = atan(in[1]->vec[0]);
r = atan(b);
break;
}
case 10: /* Power */
{
/* Only raise negative numbers by full integers */
if (in[0]->vec[0] >= 0) {
out[0]->vec[0] = pow(in[0]->vec[0], in[1]->vec[0]);
if (a >= 0) {
r = pow(a, b);
}
else {
float y_mod_1 = fabsf(fmodf(in[1]->vec[0], 1.0f));
float y_mod_1 = fabsf(fmodf(b, 1.0f));
/* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */
if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
out[0]->vec[0] = powf(in[0]->vec[0], floorf(in[1]->vec[0] + 0.5f));
r = powf(a, floorf(b + 0.5f));
}
else {
out[0]->vec[0] = 0.0f;
r = 0.0f;
}
}
@ -157,61 +162,63 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
case 11: /* Logarithm */
{
/* Don't want any imaginary numbers... */
if (in[0]->vec[0] > 0 && in[1]->vec[0] > 0)
out[0]->vec[0] = log(in[0]->vec[0]) / log(in[1]->vec[0]);
if (a > 0 && b > 0)
r = log(a) / log(b);
else
out[0]->vec[0] = 0.0;
r = 0.0;
break;
}
case 12: /* Minimum */
{
if (in[0]->vec[0] < in[1]->vec[0])
out[0]->vec[0] = in[0]->vec[0];
if (a < b)
r = a;
else
out[0]->vec[0] = in[1]->vec[0];
r = b;
break;
}
case 13: /* Maximum */
{
if (in[0]->vec[0] > in[1]->vec[0])
out[0]->vec[0] = in[0]->vec[0];
if (a > b)
r = a;
else
out[0]->vec[0] = in[1]->vec[0];
r = b;
break;
}
case 14: /* Round */
{
if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
out[0]->vec[0] = (in[0]->vec[0] < 0) ? (int)(in[0]->vec[0] - 0.5f) : (int)(in[0]->vec[0] + 0.5f);
r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
else
out[0]->vec[0] = (in[1]->vec[0] < 0) ? (int)(in[1]->vec[0] - 0.5f) : (int)(in[1]->vec[0] + 0.5f);
r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
break;
}
case 15: /* Less Than */
{
if (in[0]->vec[0] < in[1]->vec[0])
out[0]->vec[0] = 1.0f;
if (a < b)
r = 1.0f;
else
out[0]->vec[0] = 0.0f;
r = 0.0f;
break;
}
case 16: /* Greater Than */
{
if (in[0]->vec[0] > in[1]->vec[0])
out[0]->vec[0] = 1.0f;
if (a > b)
r = 1.0f;
else
out[0]->vec[0] = 0.0f;
r = 0.0f;
break;
}
case 17: /* Modulo */
{
if (in[1]->vec[0] == 0.0f)
out[0]->vec[0] = 0.0f;
if (b == 0.0f)
r = 0.0f;
else
out[0]->vec[0] = fmod(in[0]->vec[0], in[1]->vec[0]);
r = fmod(a, b);
break;
}
}
out[0]->vec[0] = r;
}
static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)

View File

@ -46,8 +46,11 @@ static bNodeSocketTemplate sh_node_sephsv_out[] = {
static void node_shader_exec_sephsv(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2],
&out[0]->vec[0], &out[1]->vec[0], &out[2]->vec[0]);
float col[3];
nodestack_get_vec(col, SOCK_VECTOR, in[0]);
rgb_to_hsv(col[0], col[1], col[2],
&out[0]->vec[0], &out[1]->vec[0], &out[2]->vec[0]);
}
static int gpu_shader_sephsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
@ -83,8 +86,12 @@ static bNodeSocketTemplate sh_node_combhsv_out[] = {
static void node_shader_exec_combhsv(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
hsv_to_rgb(in[0]->vec[0], in[1]->vec[0], in[2]->vec[0],
&out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]);
float h, s, v;
nodestack_get_vec(&h, SOCK_FLOAT, in[0]);
nodestack_get_vec(&s, SOCK_FLOAT, in[1]);
nodestack_get_vec(&v, SOCK_FLOAT, in[2]);
hsv_to_rgb(h, s, v, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]);
}
static int gpu_shader_combhsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)

View File

@ -46,9 +46,12 @@ static bNodeSocketTemplate sh_node_seprgb_out[] = {
static void node_shader_exec_seprgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[1]->vec[0] = in[0]->vec[1];
out[2]->vec[0] = in[0]->vec[2];
float col[3];
nodestack_get_vec(col, SOCK_VECTOR, in[0]);
out[0]->vec[0] = col[0];
out[1]->vec[0] = col[1];
out[2]->vec[0] = col[2];
}
static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
@ -85,9 +88,14 @@ static bNodeSocketTemplate sh_node_combrgb_out[] = {
static void node_shader_exec_combrgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[0]->vec[1] = in[1]->vec[0];
out[0]->vec[2] = in[2]->vec[0];
float r, g, b;
nodestack_get_vec(&r, SOCK_FLOAT, in[0]);
nodestack_get_vec(&g, SOCK_FLOAT, in[1]);
nodestack_get_vec(&b, SOCK_FLOAT, in[2]);
out[0]->vec[0] = r;
out[0]->vec[1] = g;
out[0]->vec[2] = b;
}
static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)

View File

@ -103,8 +103,10 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNo
{
/* stack order out: bw */
/* stack order in: col */
float col[3];
nodestack_get_vec(col, SOCK_VECTOR, in[0]);
out[0]->vec[0] = rgb_to_bw(in[0]->vec);
out[0]->vec[0] = rgb_to_bw(col);
}
static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)