[Bf-blender-cvs] [d3758892987] master: Nodes: Add Refract and Faceforward functions to Vector Maths nodes

Charlie Jolly noreply at git.blender.org
Tue Mar 23 10:59:59 CET 2021


Commit: d3758892987d76749fdf1211ed27ff77f39b5b3b
Author: Charlie Jolly
Date:   Tue Mar 23 09:21:56 2021 +0000
Branches: master
https://developer.blender.org/rBd3758892987d76749fdf1211ed27ff77f39b5b3b

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

===================================================================

M	intern/cycles/kernel/shaders/node_math.h
M	intern/cycles/kernel/shaders/node_vector_math.osl
M	intern/cycles/kernel/svm/svm_math.h
M	intern/cycles/kernel/svm/svm_math_util.h
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/nodes.cpp
M	intern/cycles/util/util_math_float3.h
M	source/blender/blenlib/BLI_float3.hh
M	source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/NOD_math_functions.hh
M	source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc
M	source/blender/nodes/intern/math_functions.cc
M	source/blender/nodes/intern/node_util.c
M	source/blender/nodes/intern/node_util.h
M	source/blender/nodes/shader/nodes/node_shader_vector_math.cc

===================================================================

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, &param1_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);
diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh
index 7e49cc89b52..cbc4d4ed366 100644
--- a/source/blender/blenlib/BLI_float3.hh
+++ b/source/blender/blenlib/BLI_float3.hh
@@ -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;
diff --git a/source/blender/gpu/sh

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list