Nodes: Add Refract and Faceforward functions to Vector Maths nodes
Cycles, Eevee, OSL, Geo, Attribute Based on outdated refract patch D6619 by @cubic_sloth `refract` and `faceforward` are standard functions in GLSL, OSL and Godot shader languages. Adding these functions provides Blender shader artists access to these standard functions. Reviewed By: brecht Differential Revision: https://developer.blender.org/D10622
This commit is contained in:
parent
4c19fcacc0
commit
d375889298
|
@ -88,6 +88,13 @@ point wrap(point value, point max, point min)
|
|||
wrap(value[2], max[2], min[2]));
|
||||
}
|
||||
|
||||
/* Built in OSL faceforward is `(dot(I, Nref) > 0) ? -N : N;` which is different to
|
||||
* GLSL `dot(Nref, I) < 0 ? N : -N` for zero values. */
|
||||
point compatible_faceforward(point vec, point incident, point reference)
|
||||
{
|
||||
return dot(reference, incident) < 0.0 ? vec : -vec;
|
||||
}
|
||||
|
||||
matrix euler_to_mat(point euler)
|
||||
{
|
||||
float cx = cos(euler[0]);
|
||||
|
|
|
@ -46,6 +46,12 @@ shader node_vector_math(string math_type = "add",
|
|||
else if (math_type == "reflect") {
|
||||
Vector = reflect(Vector1, normalize(Vector2));
|
||||
}
|
||||
else if (math_type == "refract") {
|
||||
Vector = refract(Vector1, normalize(Vector2), Scale);
|
||||
}
|
||||
else if (math_type == "faceforward") {
|
||||
Vector = compatible_faceforward(Vector1, Vector2, Vector3);
|
||||
}
|
||||
else if (math_type == "dot_product") {
|
||||
Value = dot(Vector1, Vector2);
|
||||
}
|
||||
|
|
|
@ -44,26 +44,26 @@ ccl_device void svm_node_vector_math(KernelGlobals *kg,
|
|||
int *offset)
|
||||
{
|
||||
uint value_stack_offset, vector_stack_offset;
|
||||
uint a_stack_offset, b_stack_offset, scale_stack_offset;
|
||||
uint a_stack_offset, b_stack_offset, param1_stack_offset;
|
||||
svm_unpack_node_uchar3(
|
||||
inputs_stack_offsets, &a_stack_offset, &b_stack_offset, &scale_stack_offset);
|
||||
inputs_stack_offsets, &a_stack_offset, &b_stack_offset, ¶m1_stack_offset);
|
||||
svm_unpack_node_uchar2(outputs_stack_offsets, &value_stack_offset, &vector_stack_offset);
|
||||
|
||||
float3 a = stack_load_float3(stack, a_stack_offset);
|
||||
float3 b = stack_load_float3(stack, b_stack_offset);
|
||||
float3 c = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float scale = stack_load_float(stack, scale_stack_offset);
|
||||
float param1 = stack_load_float(stack, param1_stack_offset);
|
||||
|
||||
float value;
|
||||
float3 vector;
|
||||
|
||||
/* 3 Vector Operators */
|
||||
if (type == NODE_VECTOR_MATH_WRAP) {
|
||||
if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD) {
|
||||
uint4 extra_node = read_node(kg, offset);
|
||||
c = stack_load_float3(stack, extra_node.x);
|
||||
}
|
||||
|
||||
svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, c, scale);
|
||||
svm_vector_math(&value, &vector, (NodeVectorMathType)type, a, b, c, param1);
|
||||
|
||||
if (stack_valid(value_stack_offset))
|
||||
stack_store_float(stack, value_stack_offset, value);
|
||||
|
|
|
@ -22,7 +22,7 @@ ccl_device void svm_vector_math(float *value,
|
|||
float3 a,
|
||||
float3 b,
|
||||
float3 c,
|
||||
float scale)
|
||||
float param1)
|
||||
{
|
||||
switch (type) {
|
||||
case NODE_VECTOR_MATH_ADD:
|
||||
|
@ -46,6 +46,12 @@ ccl_device void svm_vector_math(float *value,
|
|||
case NODE_VECTOR_MATH_REFLECT:
|
||||
*vector = reflect(a, b);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
*vector = refract(a, normalize(b), param1);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
*vector = faceforward(a, b, c);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||
*value = dot(a, b);
|
||||
break;
|
||||
|
@ -56,7 +62,7 @@ ccl_device void svm_vector_math(float *value,
|
|||
*value = len(a);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SCALE:
|
||||
*vector = a * scale;
|
||||
*vector = a * param1;
|
||||
break;
|
||||
case NODE_VECTOR_MATH_NORMALIZE:
|
||||
*vector = safe_normalize(a);
|
||||
|
@ -98,7 +104,7 @@ ccl_device void svm_vector_math(float *value,
|
|||
*vector = make_float3(tanf(a.x), tanf(a.y), tanf(a.z));
|
||||
break;
|
||||
default:
|
||||
*vector = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*vector = zero_float3();
|
||||
*value = 0.0f;
|
||||
}
|
||||
}
|
||||
|
@ -236,10 +242,12 @@ ccl_device float3 svm_math_blackbody_color(float t)
|
|||
return make_float3(4.70366907f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
int i = (t >= 6365.0f) ?
|
||||
5 :
|
||||
(t >= 3315.0f) ? 4 :
|
||||
(t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
|
||||
int i = (t >= 6365.0f) ? 5 :
|
||||
(t >= 3315.0f) ? 4 :
|
||||
(t >= 1902.0f) ? 3 :
|
||||
(t >= 1449.0f) ? 2 :
|
||||
(t >= 1167.0f) ? 1 :
|
||||
0;
|
||||
|
||||
ccl_constant float *r = blackbody_table_r[i];
|
||||
ccl_constant float *g = blackbody_table_g[i];
|
||||
|
|
|
@ -339,6 +339,8 @@ typedef enum NodeVectorMathType {
|
|||
NODE_VECTOR_MATH_SINE,
|
||||
NODE_VECTOR_MATH_COSINE,
|
||||
NODE_VECTOR_MATH_TANGENT,
|
||||
NODE_VECTOR_MATH_REFRACT,
|
||||
NODE_VECTOR_MATH_FACEFORWARD,
|
||||
} NodeVectorMathType;
|
||||
|
||||
typedef enum NodeClampType {
|
||||
|
|
|
@ -6091,6 +6091,9 @@ NODE_DEFINE(VectorMathNode)
|
|||
type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
|
||||
type_enum.insert("project", NODE_VECTOR_MATH_PROJECT);
|
||||
type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
|
||||
type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
|
||||
type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
|
||||
|
||||
type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
|
||||
|
||||
type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE);
|
||||
|
@ -6151,24 +6154,24 @@ void VectorMathNode::compile(SVMCompiler &compiler)
|
|||
{
|
||||
ShaderInput *vector1_in = input("Vector1");
|
||||
ShaderInput *vector2_in = input("Vector2");
|
||||
ShaderInput *scale_in = input("Scale");
|
||||
ShaderInput *param1_in = input("Scale");
|
||||
ShaderOutput *value_out = output("Value");
|
||||
ShaderOutput *vector_out = output("Vector");
|
||||
|
||||
int vector1_stack_offset = compiler.stack_assign(vector1_in);
|
||||
int vector2_stack_offset = compiler.stack_assign(vector2_in);
|
||||
int scale_stack_offset = compiler.stack_assign(scale_in);
|
||||
int param1_stack_offset = compiler.stack_assign(param1_in);
|
||||
int value_stack_offset = compiler.stack_assign_if_linked(value_out);
|
||||
int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
|
||||
|
||||
/* 3 Vector Operators */
|
||||
if (math_type == NODE_VECTOR_MATH_WRAP) {
|
||||
if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD) {
|
||||
ShaderInput *vector3_in = input("Vector3");
|
||||
int vector3_stack_offset = compiler.stack_assign(vector3_in);
|
||||
compiler.add_node(
|
||||
NODE_VECTOR_MATH,
|
||||
math_type,
|
||||
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
|
||||
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
|
||||
compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
|
||||
compiler.add_node(vector3_stack_offset);
|
||||
}
|
||||
|
@ -6176,7 +6179,7 @@ void VectorMathNode::compile(SVMCompiler &compiler)
|
|||
compiler.add_node(
|
||||
NODE_VECTOR_MATH,
|
||||
math_type,
|
||||
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, scale_stack_offset),
|
||||
compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
|
||||
compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -388,6 +388,22 @@ ccl_device_inline float3 reflect(const float3 incident, const float3 normal)
|
|||
return incident - 2.0f * unit_normal * dot(incident, unit_normal);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 refract(const float3 incident, const float3 normal, const float eta)
|
||||
{
|
||||
float k = 1.0f - eta * eta * (1.0f - dot(normal, incident) * dot(normal, incident));
|
||||
if (k < 0.0f)
|
||||
return zero_float3();
|
||||
else
|
||||
return eta * incident - (eta * dot(normal, incident) + sqrt(k)) * normal;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 faceforward(const float3 vector,
|
||||
const float3 incident,
|
||||
const float3 reference)
|
||||
{
|
||||
return (dot(reference, incident) < 0.0f) ? vector : -vector;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 project(const float3 v, const float3 v_proj)
|
||||
{
|
||||
float len_squared = dot(v_proj, v_proj);
|
||||
|
|
|
@ -191,6 +191,24 @@ struct float3 {
|
|||
return result;
|
||||
}
|
||||
|
||||
static float3 refract(const float3 &incident, const float3 &normal, const float eta)
|
||||
{
|
||||
float3 result;
|
||||
float k = 1.0f - eta * eta * (1.0f - dot(normal, incident) * dot(normal, incident));
|
||||
if (k < 0.0f) {
|
||||
result = float3(0.0f);
|
||||
}
|
||||
else {
|
||||
result = eta * incident - (eta * dot(normal, incident) + sqrt(k)) * normal;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static float3 faceforward(const float3 &vector, const float3 &incident, const float3 &reference)
|
||||
{
|
||||
return dot(reference, incident) < 0.0f ? vector : -vector;
|
||||
}
|
||||
|
||||
static float3 safe_divide(const float3 &a, const float3 &b)
|
||||
{
|
||||
float3 result;
|
||||
|
|
|
@ -138,3 +138,15 @@ void vector_math_tangent(
|
|||
{
|
||||
outVector = tan(a);
|
||||
}
|
||||
|
||||
void vector_math_refract(
|
||||
vec3 a, vec3 b, vec3 c, float scale, out vec3 outVector, out float outValue)
|
||||
{
|
||||
outVector = refract(a, normalize(b), scale);
|
||||
}
|
||||
|
||||
void vector_math_faceforward(
|
||||
vec3 a, vec3 b, vec3 c, float scale, out vec3 outVector, out float outValue)
|
||||
{
|
||||
outVector = faceforward(a, b, c);
|
||||
}
|
||||
|
|
|
@ -1550,6 +1550,8 @@ typedef enum NodeVectorMathOperation {
|
|||
NODE_VECTOR_MATH_SINE = 21,
|
||||
NODE_VECTOR_MATH_COSINE = 22,
|
||||
NODE_VECTOR_MATH_TANGENT = 23,
|
||||
NODE_VECTOR_MATH_REFRACT = 24,
|
||||
NODE_VECTOR_MATH_FACEFORWARD = 25,
|
||||
} NodeVectorMathOperation;
|
||||
|
||||
/* Boolean math node operations. */
|
||||
|
|
|
@ -224,6 +224,18 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
|
|||
0,
|
||||
"Reflect",
|
||||
"Reflect A around the normal B. B doesn't need to be normalized"},
|
||||
{NODE_VECTOR_MATH_REFRACT,
|
||||
"REFRACT",
|
||||
0,
|
||||
"Refract",
|
||||
"For a given incident vector A, surface normal B and ratio of indices of refraction, Ior, "
|
||||
"refract returns the refraction vector, R"},
|
||||
{NODE_VECTOR_MATH_FACEFORWARD,
|
||||
"FACEFORWARD",
|
||||
0,
|
||||
"Faceforward",
|
||||
"Orients a vector A to point away from a surface B as defined by its normal C. "
|
||||
"Returns (dot(B, C) < 0) ? A : -A"},
|
||||
{NODE_VECTOR_MATH_DOT_PRODUCT, "DOT_PRODUCT", 0, "Dot Product", "A dot B"},
|
||||
{0, "", ICON_NONE, NULL, NULL},
|
||||
{NODE_VECTOR_MATH_DISTANCE, "DISTANCE", 0, "Distance", "Distance between A and B"},
|
||||
|
@ -1961,7 +1973,7 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeFill_type_itemf(bContext
|
|||
|
||||
/**
|
||||
* This bit of ugly code makes sure the float / attribute option shows up instead of
|
||||
* vector / attribute if the node uses an operation that uses a float for input B.
|
||||
* vector / attribute if the node uses an operation that uses a float for input B or C.
|
||||
*/
|
||||
static const EnumPropertyItem *rna_GeometryNodeAttributeVectorMath_input_type_b_itemf(
|
||||
bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
|
||||
|
@ -1994,6 +2006,37 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeVectorMath_input_type_b_
|
|||
return item_array;
|
||||
}
|
||||
|
||||
static const EnumPropertyItem *rna_GeometryNodeAttributeVectorMath_input_type_c_itemf(
|
||||
bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
|
||||
{
|
||||
bNode *node = ptr->data;
|
||||
NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage;
|
||||
|
||||
EnumPropertyItem *item_array = NULL;
|
||||
int items_len = 0;
|
||||
for (const EnumPropertyItem *item = rna_node_geometry_attribute_input_type_items_any;
|
||||
item->identifier != NULL;
|
||||
item++) {
|
||||
if (item->value == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) {
|
||||
RNA_enum_item_add(&item_array, &items_len, item);
|
||||
}
|
||||
else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) {
|
||||
if (node_storage->operation == NODE_VECTOR_MATH_REFRACT) {
|
||||
RNA_enum_item_add(&item_array, &items_len, item);
|
||||
}
|
||||
}
|
||||
else if (item->value == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) {
|
||||
if (node_storage->operation != NODE_VECTOR_MATH_REFRACT) {
|
||||
RNA_enum_item_add(&item_array, &items_len, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
RNA_enum_item_end(&item_array, &items_len);
|
||||
|
||||
*r_free = true;
|
||||
return item_array;
|
||||
}
|
||||
|
||||
static void rna_GeometryNodeAttributeVectorMath_operation_update(Main *bmain,
|
||||
Scene *scene,
|
||||
PointerRNA *ptr)
|
||||
|
@ -8901,7 +8944,9 @@ static void def_geo_attribute_vector_math(StructRNA *srna)
|
|||
|
||||
prop = RNA_def_property(srna, "input_type_c", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_c");
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector);
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_any);
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, NULL, NULL, "rna_GeometryNodeAttributeVectorMath_input_type_c_itemf");
|
||||
RNA_def_property_ui_text(prop, "Input Type C", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
|
|
@ -351,6 +351,35 @@ inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOpera
|
|||
return dispatch([](float3 a, float3 b, float3 c) {
|
||||
return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
|
||||
});
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
return dispatch([](float3 a, float3 b, float3 c) { return float3::faceforward(a, b, c); });
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature.
|
||||
*/
|
||||
template<typename Callback>
|
||||
inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperation operation,
|
||||
Callback &&callback)
|
||||
{
|
||||
const FloatMathOperationInfo *info = get_float3_math_operation_info(operation);
|
||||
if (info == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is just a utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto math_function) -> bool {
|
||||
callback(math_function, *info);
|
||||
return true;
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
return dispatch([](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ static bNodeSocketTemplate geo_node_attribute_vector_math_in[] = {
|
|||
{SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
|
||||
{SOCK_STRING, N_("C")},
|
||||
{SOCK_VECTOR, N_("C"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
|
||||
{SOCK_FLOAT, N_("C"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
|
||||
{SOCK_STRING, N_("Result")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
@ -65,7 +66,8 @@ static bool operation_use_input_b(const NodeVectorMathOperation operation)
|
|||
|
||||
static bool operation_use_input_c(const NodeVectorMathOperation operation)
|
||||
{
|
||||
return operation == NODE_VECTOR_MATH_WRAP;
|
||||
return ELEM(
|
||||
operation, NODE_VECTOR_MATH_WRAP, NODE_VECTOR_MATH_REFRACT, NODE_VECTOR_MATH_FACEFORWARD);
|
||||
}
|
||||
|
||||
static void geo_node_attribute_vector_math_layout(uiLayout *layout,
|
||||
|
@ -97,6 +99,14 @@ static CustomDataType operation_get_read_type_b(const NodeVectorMathOperation op
|
|||
return CD_PROP_FLOAT3;
|
||||
}
|
||||
|
||||
static CustomDataType operation_get_read_type_c(const NodeVectorMathOperation operation)
|
||||
{
|
||||
if (operation == NODE_VECTOR_MATH_REFRACT) {
|
||||
return CD_PROP_FLOAT;
|
||||
}
|
||||
return CD_PROP_FLOAT3;
|
||||
}
|
||||
|
||||
static void geo_node_attribute_vector_math_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodeAttributeVectorMath *data = (NodeAttributeVectorMath *)MEM_callocN(
|
||||
|
@ -132,6 +142,8 @@ static CustomDataType operation_get_result_type(const NodeVectorMathOperation op
|
|||
case NODE_VECTOR_MATH_SINE:
|
||||
case NODE_VECTOR_MATH_COSINE:
|
||||
case NODE_VECTOR_MATH_TANGENT:
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
return CD_PROP_FLOAT3;
|
||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||
case NODE_VECTOR_MATH_DISTANCE:
|
||||
|
@ -223,6 +235,37 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const Float3ReadAttribute &inpu
|
|||
UNUSED_VARS_NDEBUG(success);
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_fl3_fl_to_fl3(const Float3ReadAttribute &input_a,
|
||||
const Float3ReadAttribute &input_b,
|
||||
const FloatReadAttribute &input_c,
|
||||
Float3WriteAttribute result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
|
||||
Span<float3> span_a = input_a.get_span();
|
||||
Span<float3> span_b = input_b.get_span();
|
||||
Span<float> span_c = input_c.get_span();
|
||||
MutableSpan<float3> span_result = result.get_span_for_write_only();
|
||||
|
||||
bool success = try_dispatch_float_math_fl3_fl3_fl_to_fl3(
|
||||
operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) {
|
||||
for (const int i : IndexRange(size)) {
|
||||
const float3 a = span_a[i];
|
||||
const float3 b = span_b[i];
|
||||
const float c = span_c[i];
|
||||
const float3 out = math_function(a, b, c);
|
||||
span_result[i] = out;
|
||||
}
|
||||
});
|
||||
|
||||
result.apply_span();
|
||||
|
||||
/* The operation is not supported by this node currently. */
|
||||
BLI_assert(success);
|
||||
UNUSED_VARS_NDEBUG(success);
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_fl3_to_fl(const Float3ReadAttribute &input_a,
|
||||
const Float3ReadAttribute &input_b,
|
||||
FloatWriteAttribute result,
|
||||
|
@ -364,7 +407,7 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
|||
const bool use_input_b = operation_use_input_b(operation);
|
||||
const CustomDataType read_type_b = operation_get_read_type_b(operation);
|
||||
const bool use_input_c = operation_use_input_c(operation);
|
||||
const CustomDataType read_type_c = CD_PROP_FLOAT3;
|
||||
const CustomDataType read_type_c = operation_get_read_type_c(operation);
|
||||
|
||||
/* The result domain is always point for now. */
|
||||
const CustomDataType result_type = operation_get_result_type(operation);
|
||||
|
@ -433,9 +476,14 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
|||
do_math_operation_fl3_to_fl3(*attribute_a, *attribute_result, operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_WRAP:
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
do_math_operation_fl3_fl3_fl3_to_fl3(
|
||||
*attribute_a, *attribute_b, *attribute_c, *attribute_result, operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
do_math_operation_fl3_fl3_fl_to_fl3(
|
||||
*attribute_a, *attribute_b, *attribute_c, *attribute_result, operation);
|
||||
break;
|
||||
}
|
||||
attribute_result.save();
|
||||
}
|
||||
|
|
|
@ -205,6 +205,10 @@ const FloatMathOperationInfo *get_float3_math_operation_info(const int operation
|
|||
RETURN_OPERATION_INFO("Cosine", "vector_math_cosine");
|
||||
case NODE_VECTOR_MATH_TANGENT:
|
||||
RETURN_OPERATION_INFO("Tangent", "vector_math_tangent");
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
RETURN_OPERATION_INFO("Refract", "vector_math_refract");
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
RETURN_OPERATION_INFO("Faceforward", "vector_math_faceforward");
|
||||
}
|
||||
|
||||
#undef RETURN_OPERATION_INFO
|
||||
|
|
|
@ -90,6 +90,13 @@ void node_sock_label(bNodeSocket *sock, const char *name)
|
|||
BLI_strncpy(sock->label, name, MAX_NAME);
|
||||
}
|
||||
|
||||
void node_sock_label_clear(bNodeSocket *sock)
|
||||
{
|
||||
if (sock->label[0] != '\0') {
|
||||
sock->label[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void node_math_update(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *sock1 = BLI_findlink(&node->inputs, 0);
|
||||
|
@ -127,15 +134,9 @@ void node_math_update(bNodeTree *UNUSED(ntree), bNode *node)
|
|||
NODE_MATH_SMOOTH_MIN,
|
||||
NODE_MATH_SMOOTH_MAX));
|
||||
|
||||
if (sock1->label[0] != '\0') {
|
||||
sock1->label[0] = '\0';
|
||||
}
|
||||
if (sock2->label[0] != '\0') {
|
||||
sock2->label[0] = '\0';
|
||||
}
|
||||
if (sock3->label[0] != '\0') {
|
||||
sock3->label[0] = '\0';
|
||||
}
|
||||
node_sock_label_clear(sock1);
|
||||
node_sock_label_clear(sock2);
|
||||
node_sock_label_clear(sock3);
|
||||
|
||||
switch (node->custom1) {
|
||||
case NODE_MATH_WRAP:
|
||||
|
|
|
@ -71,6 +71,7 @@ extern void *node_initexec_curves(struct bNodeExecContext *context,
|
|||
|
||||
/**** Updates ****/
|
||||
void node_sock_label(struct bNodeSocket *sock, const char *name);
|
||||
void node_sock_label_clear(struct bNodeSocket *sock);
|
||||
void node_math_update(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
/**** Labels ****/
|
||||
|
|
|
@ -88,6 +88,10 @@ static const char *gpu_shader_get_name(int mode)
|
|||
return "vector_math_cosine";
|
||||
case NODE_VECTOR_MATH_TANGENT:
|
||||
return "vector_math_tangent";
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
return "vector_math_refract";
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
return "vector_math_faceforward";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -128,8 +132,10 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
|
|||
NODE_VECTOR_MATH_ABSOLUTE,
|
||||
NODE_VECTOR_MATH_FRACTION,
|
||||
NODE_VECTOR_MATH_NORMALIZE));
|
||||
nodeSetSocketAvailability(sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP));
|
||||
nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE);
|
||||
nodeSetSocketAvailability(
|
||||
sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP, NODE_VECTOR_MATH_FACEFORWARD));
|
||||
nodeSetSocketAvailability(sockScale,
|
||||
ELEM(node->custom1, NODE_VECTOR_MATH_SCALE, NODE_VECTOR_MATH_REFRACT));
|
||||
nodeSetSocketAvailability(sockVector,
|
||||
!ELEM(node->custom1,
|
||||
NODE_VECTOR_MATH_LENGTH,
|
||||
|
@ -142,13 +148,14 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
|
|||
NODE_VECTOR_MATH_DOT_PRODUCT));
|
||||
|
||||
/* Labels */
|
||||
if (sockB->label[0] != '\0') {
|
||||
sockB->label[0] = '\0';
|
||||
}
|
||||
if (sockC->label[0] != '\0') {
|
||||
sockC->label[0] = '\0';
|
||||
}
|
||||
node_sock_label_clear(sockB);
|
||||
node_sock_label_clear(sockC);
|
||||
node_sock_label_clear(sockScale);
|
||||
switch (node->custom1) {
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
node_sock_label(sockB, "Incident");
|
||||
node_sock_label(sockC, "Reference");
|
||||
break;
|
||||
case NODE_VECTOR_MATH_WRAP:
|
||||
node_sock_label(sockB, "Max");
|
||||
node_sock_label(sockC, "Min");
|
||||
|
@ -156,6 +163,12 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
|
|||
case NODE_VECTOR_MATH_SNAP:
|
||||
node_sock_label(sockB, "Increment");
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
node_sock_label(sockScale, "Ior");
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SCALE:
|
||||
node_sock_label(sockScale, "Scale");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +199,6 @@ static const blender::fn::MultiFunction &get_multi_function(
|
|||
"Divide", [](float3 a, float3 b) { return float3::safe_divide(a, b); }};
|
||||
return fn;
|
||||
}
|
||||
|
||||
case NODE_VECTOR_MATH_CROSS_PRODUCT: {
|
||||
static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
|
||||
"Cross Product", float3::cross_high_precision};
|
||||
|
@ -205,7 +217,6 @@ static const blender::fn::MultiFunction &get_multi_function(
|
|||
static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Dot Product", float3::dot};
|
||||
return fn;
|
||||
}
|
||||
|
||||
case NODE_VECTOR_MATH_DISTANCE: {
|
||||
static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Distance",
|
||||
float3::distance};
|
||||
|
@ -226,7 +237,17 @@ static const blender::fn::MultiFunction &get_multi_function(
|
|||
"Normalize", [](float3 a) { return a.normalized(); }};
|
||||
return fn;
|
||||
}
|
||||
|
||||
case NODE_VECTOR_MATH_REFRACT: {
|
||||
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
|
||||
"Refract",
|
||||
[](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); }};
|
||||
return fn;
|
||||
}
|
||||
case NODE_VECTOR_MATH_FACEFORWARD: {
|
||||
static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
|
||||
"Faceforward", float3::faceforward};
|
||||
return fn;
|
||||
}
|
||||
case NODE_VECTOR_MATH_SNAP: {
|
||||
return builder.get_not_implemented_fn();
|
||||
}
|
||||
|
@ -263,7 +284,6 @@ static const blender::fn::MultiFunction &get_multi_function(
|
|||
case NODE_VECTOR_MATH_TANGENT: {
|
||||
return builder.get_not_implemented_fn();
|
||||
}
|
||||
|
||||
default:
|
||||
BLI_assert(false);
|
||||
return builder.get_not_implemented_fn();
|
||||
|
|
Loading…
Reference in New Issue