From d3758892987d76749fdf1211ed27ff77f39b5b3b Mon Sep 17 00:00:00 2001 From: Charlie Jolly Date: Tue, 23 Mar 2021 09:21:56 +0000 Subject: 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 --- intern/cycles/kernel/shaders/node_math.h | 7 +++++++ intern/cycles/kernel/shaders/node_vector_math.osl | 6 ++++++ intern/cycles/kernel/svm/svm_math.h | 10 +++++----- intern/cycles/kernel/svm/svm_math_util.h | 22 +++++++++++++++------- intern/cycles/kernel/svm/svm_types.h | 2 ++ intern/cycles/render/nodes.cpp | 13 ++++++++----- intern/cycles/util/util_math_float3.h | 16 ++++++++++++++++ 7 files changed, 59 insertions(+), 17 deletions(-) (limited to 'intern') diff --git a/intern/cycles/kernel/shaders/node_math.h b/intern/cycles/kernel/shaders/node_math.h index 3a008721d5e..2da73b94212 100644 --- a/intern/cycles/kernel/shaders/node_math.h +++ b/intern/cycles/kernel/shaders/node_math.h @@ -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]); diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl index 30f0b1daf4c..3963c23ea9c 100644 --- a/intern/cycles/kernel/shaders/node_vector_math.osl +++ b/intern/cycles/kernel/shaders/node_vector_math.osl @@ -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); } diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index 12a2bbdeb9b..dda2e50f916 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -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); diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index d1e1fa87e53..389c44ab1da 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -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]; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 4a00afc1d7f..64a8f82a094 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -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 { diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 7d485fa3f03..f3d420c6fcb 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -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)); } } diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h index 67c5c61e4c0..9673c043189 100644 --- a/intern/cycles/util/util_math_float3.h +++ b/intern/cycles/util/util_math_float3.h @@ -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); -- cgit v1.2.3