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:
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.
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue