Shading: Add Vertex Color node.
authorOmarSquircleArt <omar.squircleart@gmail.com>
Thu, 12 Sep 2019 15:42:13 +0000 (17:42 +0200)
committerOmarSquircleArt <omar.squircleart@gmail.com>
Thu, 12 Sep 2019 15:42:13 +0000 (17:42 +0200)
This patch adds a new Vertex Color node. The node also returns the alpha
of the vertex color layer as an output.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5767

34 files changed:
intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/geom/geom_patch.h
intern/cycles/kernel/geom/geom_primitive.h
intern/cycles/kernel/geom/geom_subd_triangle.h
intern/cycles/kernel/geom/geom_triangle.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/shaders/CMakeLists.txt
intern/cycles/kernel/shaders/node_vertex_color.osl [new file with mode: 0644]
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_attribute.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/kernel/svm/svm_vertex_color.h [new file with mode: 0644]
intern/cycles/render/attribute.cpp
intern/cycles/render/mesh.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/util/util_color.h
intern/cycles/util/util_param.h
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/editors/space_node/drawnode.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_material_library.h
source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_shader.h
source/blender/nodes/NOD_static_types.h
source/blender/nodes/shader/nodes/node_shader_vertex_color.c [new file with mode: 0644]

index 551866f7fced1d7c01e5caf702aa14119a56408a..30417e8544189323266350855f81dbc5a98c6abc 100644 (file)
@@ -335,7 +335,7 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
         continue;
 
       Attribute *attr = mesh->subd_attributes.add(
-          ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+          ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CORNER_BYTE);
 
       BL::Mesh::polygons_iterator p;
       uchar4 *cdata = attr->data_uchar4();
@@ -343,9 +343,9 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
       for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
         int n = p->loop_total();
         for (int i = 0; i < n; i++) {
-          float3 color = get_float3(l->data[p->loop_start() + i].color());
+          float4 color = get_float4(l->data[p->loop_start() + i].color());
           /* Compress/encode vertex color using the sRGB curve. */
-          *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
+          *(cdata++) = color_float4_to_uchar4(color_srgb_to_linear_v4(color));
         }
       }
     }
@@ -357,21 +357,21 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
         continue;
 
       Attribute *attr = mesh->attributes.add(
-          ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+          ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CORNER_BYTE);
 
       BL::Mesh::loop_triangles_iterator t;
       uchar4 *cdata = attr->data_uchar4();
 
       for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
         int3 li = get_int3(t->loops());
-        float3 c1 = get_float3(l->data[li[0]].color());
-        float3 c2 = get_float3(l->data[li[1]].color());
-        float3 c3 = get_float3(l->data[li[2]].color());
+        float4 c1 = get_float4(l->data[li[0]].color());
+        float4 c2 = get_float4(l->data[li[1]].color());
+        float4 c3 = get_float4(l->data[li[2]].color());
 
         /* Compress/encode vertex color using the sRGB curve. */
-        cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
-        cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
-        cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
+        cdata[0] = color_float4_to_uchar4(color_srgb_to_linear_v4(c1));
+        cdata[1] = color_float4_to_uchar4(color_srgb_to_linear_v4(c2));
+        cdata[2] = color_float4_to_uchar4(color_srgb_to_linear_v4(c3));
         cdata += 3;
       }
     }
index 257c799a3e0eca084cb1303b7f0266abef13455d..362155f22ac6c0cf34b644487fa121d936ca4295 100644 (file)
@@ -590,6 +590,12 @@ static ShaderNode *add_node(Scene *scene,
   else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) {
     node = new VolumeInfoNode();
   }
+  else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) {
+    BL::ShaderNodeVertexColor b_vertex_color_node(b_node);
+    VertexColorNode *vertex_color_node = new VertexColorNode();
+    vertex_color_node->layer_name = b_vertex_color_node.layer_name();
+    node = vertex_color_node;
+  }
   else if (b_node.is_a(&RNA_ShaderNodeBump)) {
     BL::ShaderNodeBump b_bump_node(b_node);
     BumpNode *bump = new BumpNode();
index 04df49aa058d40ddfe0b609a3b899dd7d2764580..41e57bb3e434bc7b133eccbcda12a8d3ff7d486f 100644 (file)
@@ -223,6 +223,7 @@ set(SRC_SVM_HEADERS
   svm/svm_voxel.h
   svm/svm_wave.h
   svm/svm_white_noise.h
+  svm/svm_vertex_color.h
 )
 
 set(SRC_GEOM_HEADERS
index df19199f68e9ef78f5b61efeec4ccdcf39806f36..8b4b91b96c8b81b01547e12aa892c2e62d067b69 100644 (file)
@@ -380,15 +380,15 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg,
   return val;
 }
 
-ccl_device float3 patch_eval_uchar4(KernelGlobals *kg,
+ccl_device float4 patch_eval_uchar4(KernelGlobals *kg,
                                     const ShaderData *sd,
                                     int offset,
                                     int patch,
                                     float u,
                                     float v,
                                     int channel,
-                                    float3 *du,
-                                    float3 *dv)
+                                    float4 *du,
+                                    float4 *dv)
 {
   int indices[PATCH_MAX_CONTROL_VERTS];
   float weights[PATCH_MAX_CONTROL_VERTS];
@@ -398,14 +398,14 @@ ccl_device float3 patch_eval_uchar4(KernelGlobals *kg,
   int num_control = patch_eval_control_verts(
       kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
 
-  float3 val = make_float3(0.0f, 0.0f, 0.0f);
+  float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
   if (du)
-    *du = make_float3(0.0f, 0.0f, 0.0f);
+    *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
   if (dv)
-    *dv = make_float3(0.0f, 0.0f, 0.0f);
+    *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
 
   for (int i = 0; i < num_control; i++) {
-    float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]));
+    float4 v = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]));
 
     val += v * weights[i];
     if (du)
index 7f2b52a24c448c0cf838961388dbeb32d840372e..9a91da79f58058e8a2f1b2e12081f8b14a2762eb 100644 (file)
@@ -162,6 +162,27 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
   }
 }
 
+ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg,
+                                                    const ShaderData *sd,
+                                                    const AttributeDescriptor desc,
+                                                    float4 *dx,
+                                                    float4 *dy)
+{
+  if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+    if (subd_triangle_patch(kg, sd) == ~0)
+      return triangle_attribute_float4(kg, sd, desc, dx, dy);
+    else
+      return subd_triangle_attribute_float4(kg, sd, desc, dx, dy);
+  }
+  else {
+    if (dx)
+      *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+    if (dy)
+      *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+    return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+  }
+}
+
 ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
                                                             const ShaderData *sd,
                                                             const AttributeDescriptor desc,
index 8d5b3c12833a374b38459a5a173c59043886b6a2..81bac6e6ee1fb0a49dc93c5964b1f8167f0806f8 100644 (file)
@@ -382,13 +382,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
     float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
 
     float3 a, dads, dadt;
-
-    if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
-      a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
-    }
-    else {
-      a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
-    }
+    a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
 
 #  ifdef __RAY_DIFFERENTIALS__
     if (dx || dy) {
@@ -460,7 +454,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
 
     return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
   }
-  else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+  else if (desc.element == ATTR_ELEMENT_CORNER) {
     float2 uv[3];
     subd_triangle_patch_uv(kg, sd, uv);
 
@@ -469,18 +463,10 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
 
     float3 f0, f1, f2, f3;
 
-    if (desc.element == ATTR_ELEMENT_CORNER) {
-      f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
-      f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset));
-      f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset));
-      f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
-    }
-    else {
-      f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
-      f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
-      f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
-      f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
-    }
+    f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
+    f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset));
+    f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset));
+    f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
 
     if (subd_triangle_patch_num_corners(kg, patch) != 4) {
       f1 = (f1 + f0) * 0.5f;
@@ -510,4 +496,102 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
   }
 }
 
+ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg,
+                                                          const ShaderData *sd,
+                                                          const AttributeDescriptor desc,
+                                                          float4 *dx,
+                                                          float4 *dy)
+{
+  int patch = subd_triangle_patch(kg, sd);
+
+#ifdef __PATCH_EVAL__
+  if (desc.flags & ATTR_SUBDIVIDED) {
+    float2 uv[3];
+    subd_triangle_patch_uv(kg, sd, uv);
+
+    float2 dpdu = uv[0] - uv[2];
+    float2 dpdv = uv[1] - uv[2];
+
+    /* p is [s, t] */
+    float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
+
+    float4 dads, dadt;
+
+    float4 a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+
+#  ifdef __RAY_DIFFERENTIALS__
+    if (dx || dy) {
+      float dsdu = dpdu.x;
+      float dtdu = dpdu.y;
+      float dsdv = dpdv.x;
+      float dtdv = dpdv.y;
+
+      if (dx) {
+        float dudx = sd->du.dx;
+        float dvdx = sd->dv.dx;
+
+        float dsdx = dsdu * dudx + dsdv * dvdx;
+        float dtdx = dtdu * dudx + dtdv * dvdx;
+
+        *dx = dads * dsdx + dadt * dtdx;
+      }
+      if (dy) {
+        float dudy = sd->du.dy;
+        float dvdy = sd->dv.dy;
+
+        float dsdy = dsdu * dudy + dsdv * dvdy;
+        float dtdy = dtdu * dudy + dtdv * dvdy;
+
+        *dy = dads * dsdy + dadt * dtdy;
+      }
+    }
+#  endif
+    return a;
+  }
+  else
+#endif /* __PATCH_EVAL__ */
+      if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+    float2 uv[3];
+    subd_triangle_patch_uv(kg, sd, uv);
+
+    int corners[4];
+    subd_triangle_patch_corners(kg, patch, corners);
+
+    float4 f0 = color_uchar4_to_float4(
+        kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
+    float4 f1 = color_uchar4_to_float4(
+        kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
+    float4 f2 = color_uchar4_to_float4(
+        kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
+    float4 f3 = color_uchar4_to_float4(
+        kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
+
+    if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+      f1 = (f1 + f0) * 0.5f;
+      f3 = (f3 + f0) * 0.5f;
+    }
+
+    float4 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+    float4 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+    float4 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+    if (dx)
+      *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+    if (dy)
+      *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
+#endif
+
+    return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+  }
+  else {
+    if (dx)
+      *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+    if (dy)
+      *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+    return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+  }
+}
+
 CCL_NAMESPACE_END
index 9938c0ba2c3080a92b4e1497ae531ea07ac302e2..fdb7f655f64ebc3f66fea5ec6fca922ce0110e46 100644 (file)
@@ -255,20 +255,13 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
 
     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
   }
-  else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+  else if (desc.element == ATTR_ELEMENT_CORNER) {
     int tri = desc.offset + sd->prim * 3;
     float3 f0, f1, f2;
 
-    if (desc.element == ATTR_ELEMENT_CORNER) {
-      f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
-      f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
-      f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
-    }
-    else {
-      f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0));
-      f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1));
-      f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2));
-    }
+    f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
+    f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
+    f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
 
 #ifdef __RAY_DIFFERENTIALS__
     if (dx)
@@ -289,4 +282,36 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
   }
 }
 
+ccl_device float4 triangle_attribute_float4(KernelGlobals *kg,
+                                            const ShaderData *sd,
+                                            const AttributeDescriptor desc,
+                                            float4 *dx,
+                                            float4 *dy)
+{
+  if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+    int tri = desc.offset + sd->prim * 3;
+
+    float4 f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0));
+    float4 f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1));
+    float4 f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2));
+
+#ifdef __RAY_DIFFERENTIALS__
+    if (dx)
+      *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+    if (dy)
+      *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
+#endif
+
+    return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+  }
+  else {
+    if (dx)
+      *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+    if (dy)
+      *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+    return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+  }
+}
+
 CCL_NAMESPACE_END
index 415de9cd66b7dd375a212bf83a8aaee07ef81dac..2698ed59e648c0fd3495d06f93cafc009a4b5937 100644 (file)
@@ -483,6 +483,65 @@ static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void
   return set_attribute_float3(fv, type, derivatives, val);
 }
 
+/* Attributes with the TypeRGBA type descriptor should be retrived and stored
+ * in a float array of size 4 (e.g. node_vertex_color.osl), this array have
+ * a type descriptor TypeFloatArray4. If the storage is not a TypeFloatArray4,
+ * we either store the first three components in a vector, store the average of
+ * the components in a float, or fail the retrival and do nothing. We allow
+ * this for the correct operation of the Attribute node.
+ */
+
+static bool set_attribute_float4(float4 f[3], TypeDesc type, bool derivatives, void *val)
+{
+  float *fval = (float *)val;
+  if (type == TypeFloatArray4) {
+    fval[0] = f[0].x;
+    fval[1] = f[0].y;
+    fval[2] = f[0].z;
+    fval[3] = f[0].w;
+
+    if (derivatives) {
+      fval[4] = f[1].x;
+      fval[5] = f[1].y;
+      fval[6] = f[1].z;
+      fval[7] = f[1].w;
+
+      fval[8] = f[2].x;
+      fval[9] = f[2].y;
+      fval[10] = f[2].z;
+      fval[11] = f[2].w;
+    }
+    return true;
+  }
+  else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+           type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+    fval[0] = f[0].x;
+    fval[1] = f[0].y;
+    fval[2] = f[0].z;
+
+    if (derivatives) {
+      fval[3] = f[1].x;
+      fval[4] = f[1].y;
+      fval[5] = f[1].z;
+
+      fval[6] = f[2].x;
+      fval[7] = f[2].y;
+      fval[8] = f[2].z;
+    }
+    return true;
+  }
+  else if (type == TypeDesc::TypeFloat) {
+    fval[0] = average(float4_to_float3(f[0]));
+
+    if (derivatives) {
+      fval[1] = average(float4_to_float3(f[1]));
+      fval[2] = average(float4_to_float3(f[2]));
+    }
+    return true;
+  }
+  return false;
+}
+
 static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
 {
   if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
@@ -629,6 +688,12 @@ static bool get_primitive_attribute(KernelGlobals *kg,
         kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
     return set_attribute_float(fval, type, derivatives, val);
   }
+  else if (attr.type == TypeRGBA) {
+    float4 fval[3];
+    fval[0] = primitive_attribute_float4(
+        kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+    return set_attribute_float4(fval, type, derivatives, val);
+  }
   else {
     return false;
   }
index 38ba113a18404aa8a7e949238d23fea4e8870f65..f4258da70d38a7919e888dca5fcb26871b011561 100644 (file)
@@ -80,6 +80,7 @@ set(SRC_OSL
   node_vector_math.osl
   node_vector_transform.osl
   node_velvet_bsdf.osl
+  node_vertex_color.osl
   node_voronoi_texture.osl
   node_voxel_texture.osl
   node_wavelength.osl
diff --git a/intern/cycles/kernel/shaders/node_vertex_color.osl b/intern/cycles/kernel/shaders/node_vertex_color.osl
new file mode 100644 (file)
index 0000000..1997a69
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+
+shader node_vertex_color(string bump_offset = "center",
+                         string layer_name = "",
+                         output color Color = 0.0,
+                         output float Alpha = 0.0)
+{
+  float vertex_color[4];
+  if (getattribute(layer_name, vertex_color)) {
+    Color = color(vertex_color[0], vertex_color[1], vertex_color[2]);
+    Alpha = vertex_color[3];
+
+    if (bump_offset == "dx") {
+      Color += Dx(Color);
+      Alpha += Dx(Alpha);
+    }
+    else if (bump_offset == "dy") {
+      Color += Dy(Color);
+      Alpha += Dy(Alpha);
+    }
+  } else {
+    warning("%s", "Invalid attribute.");
+  }
+}
index 8de66a0496349febcafae9f30da1c0783dd9151a..4fc5e633e3bf8ce74499f24cf0edf7496e0488d2 100644 (file)
@@ -205,6 +205,7 @@ CCL_NAMESPACE_END
 #include "kernel/svm/svm_map_range.h"
 #include "kernel/svm/svm_clamp.h"
 #include "kernel/svm/svm_white_noise.h"
+#include "kernel/svm/svm_vertex_color.h"
 
 #ifdef __SHADER_RAYTRACE__
 #  include "kernel/svm/svm_ao.h"
@@ -289,6 +290,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
       case NODE_ATTR:
         svm_node_attr(kg, sd, stack, node);
         break;
+      case NODE_VERTEX_COLOR:
+        svm_node_vertex_color(kg, sd, stack, node.y, node.z, node.w);
+        break;
 #  if NODES_FEATURE(NODE_FEATURE_BUMP)
       case NODE_GEOMETRY_BUMP_DX:
         svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
@@ -328,6 +332,12 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
       case NODE_ATTR_BUMP_DY:
         svm_node_attr_bump_dy(kg, sd, stack, node);
         break;
+      case NODE_VERTEX_COLOR_BUMP_DX:
+        svm_node_vertex_color_bump_dx(kg, sd, stack, node.y, node.z, node.w);
+        break;
+      case NODE_VERTEX_COLOR_BUMP_DY:
+        svm_node_vertex_color_bump_dy(kg, sd, stack, node.y, node.z, node.w);
+        break;
       case NODE_TEX_COORD_BUMP_DX:
         svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
         break;
index eaee0f9e4eecc3b5d963901535b19deb452fbfae..fc7a3ba3f5a79a529263e672111f64a4428b42d1 100644 (file)
@@ -69,6 +69,15 @@ ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, u
       stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
     }
   }
+  else if (desc.type == NODE_ATTR_RGBA) {
+    float4 f = primitive_attribute_float4(kg, sd, desc, NULL, NULL);
+    if (type == NODE_ATTR_FLOAT) {
+      stack_store_float(stack, out_offset, average(float4_to_float3(f)));
+    }
+    else {
+      stack_store_float3(stack, out_offset, float4_to_float3(f));
+    }
+  }
   else {
     float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
     if (type == NODE_ATTR_FLOAT) {
@@ -107,6 +116,16 @@ ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *
       stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f));
     }
   }
+  else if (desc.type == NODE_ATTR_RGBA) {
+    float4 dx;
+    float4 f = primitive_attribute_float4(kg, sd, desc, &dx, NULL);
+    if (type == NODE_ATTR_FLOAT) {
+      stack_store_float(stack, out_offset, average(float4_to_float3(f + dx)));
+    }
+    else {
+      stack_store_float3(stack, out_offset, float4_to_float3(f + dx));
+    }
+  }
   else {
     float3 dx;
     float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
@@ -146,6 +165,16 @@ ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *
       stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f));
     }
   }
+  else if (desc.type == NODE_ATTR_RGBA) {
+    float4 dy;
+    float4 f = primitive_attribute_float4(kg, sd, desc, NULL, &dy);
+    if (type == NODE_ATTR_FLOAT) {
+      stack_store_float(stack, out_offset, average(float4_to_float3(f + dy)));
+    }
+    else {
+      stack_store_float3(stack, out_offset, float4_to_float3(f + dy));
+    }
+  }
   else {
     float3 dy;
     float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
index 65e2dacedaeb111612cb15f3a8d92e34c9a9a8c1..a6f2327dada381e320a6ed009db21a77bd1207b3 100644 (file)
@@ -142,12 +142,16 @@ typedef enum ShaderNodeType {
   NODE_CLAMP,
   NODE_TEXTURE_MAPPING,
   NODE_TEX_WHITE_NOISE,
+  NODE_VERTEX_COLOR,
+  NODE_VERTEX_COLOR_BUMP_DX,
+  NODE_VERTEX_COLOR_BUMP_DY,
 } ShaderNodeType;
 
 typedef enum NodeAttributeType {
   NODE_ATTR_FLOAT = 0,
   NODE_ATTR_FLOAT2,
   NODE_ATTR_FLOAT3,
+  NODE_ATTR_RGBA,
   NODE_ATTR_MATRIX
 } NodeAttributeType;
 
diff --git a/intern/cycles/kernel/svm/svm_vertex_color.h b/intern/cycles/kernel/svm/svm_vertex_color.h
new file mode 100644 (file)
index 0000000..3c105b1
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device void svm_node_vertex_color(KernelGlobals *kg,
+                                      ShaderData *sd,
+                                      float *stack,
+                                      uint layer_id,
+                                      uint color_offset,
+                                      uint alpha_offset)
+{
+  AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
+  if (descriptor.offset != ATTR_STD_NOT_FOUND) {
+    float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, NULL);
+    stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
+    stack_store_float(stack, alpha_offset, vertex_color.w);
+  }
+  else {
+    stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f));
+    stack_store_float(stack, alpha_offset, 0.0f);
+  }
+}
+
+#ifndef __KERNEL_CUDA__
+ccl_device
+#else
+ccl_device_noinline
+#endif
+    void
+    svm_node_vertex_color_bump_dx(KernelGlobals *kg,
+                                  ShaderData *sd,
+                                  float *stack,
+                                  uint layer_id,
+                                  uint color_offset,
+                                  uint alpha_offset)
+{
+  AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
+  if (descriptor.offset != ATTR_STD_NOT_FOUND) {
+    float4 dx;
+    float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, &dx, NULL);
+    vertex_color += dx;
+    stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
+    stack_store_float(stack, alpha_offset, vertex_color.w);
+  }
+  else {
+    stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f));
+    stack_store_float(stack, alpha_offset, 0.0f);
+  }
+}
+
+#ifndef __KERNEL_CUDA__
+ccl_device
+#else
+ccl_device_noinline
+#endif
+    void
+    svm_node_vertex_color_bump_dy(KernelGlobals *kg,
+                                  ShaderData *sd,
+                                  float *stack,
+                                  uint layer_id,
+                                  uint color_offset,
+                                  uint alpha_offset)
+{
+  AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
+  if (descriptor.offset != ATTR_STD_NOT_FOUND) {
+    float4 dy;
+    float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, &dy);
+    vertex_color += dy;
+    stack_store_float3(stack, color_offset, float4_to_float3(vertex_color));
+    stack_store_float(stack, alpha_offset, vertex_color.w);
+  }
+  else {
+    stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f));
+    stack_store_float(stack, alpha_offset, 0.0f);
+  }
+}
+
+CCL_NAMESPACE_END
index f1341d50b9dab00303faa56797d409064ca5429b..0fa1142f3544ee2029fab196b5a4eebb9eeb2f3f 100644 (file)
@@ -48,7 +48,8 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
   /* string and matrix not supported! */
   assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
          type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
-         type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2);
+         type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2 ||
+         type == TypeRGBA);
 }
 
 void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
index 3d2cc98d38b6e5482023e9969845abbc962e5930..9be078b6fcade969f0c24016f061eaa53c2ba052 100644 (file)
@@ -1223,6 +1223,8 @@ void MeshManager::update_osl_attributes(Device *device,
           osl_attr.type = TypeDesc::TypeMatrix;
         else if (req.triangle_type == TypeFloat2)
           osl_attr.type = TypeFloat2;
+        else if (req.triangle_type == TypeRGBA)
+          osl_attr.type = TypeRGBA;
         else
           osl_attr.type = TypeDesc::TypeColor;
 
@@ -1246,6 +1248,8 @@ void MeshManager::update_osl_attributes(Device *device,
           osl_attr.type = TypeDesc::TypeMatrix;
         else if (req.curve_type == TypeFloat2)
           osl_attr.type = TypeFloat2;
+        else if (req.curve_type == TypeRGBA)
+          osl_attr.type = TypeRGBA;
         else
           osl_attr.type = TypeDesc::TypeColor;
 
@@ -1269,6 +1273,8 @@ void MeshManager::update_osl_attributes(Device *device,
           osl_attr.type = TypeDesc::TypeMatrix;
         else if (req.subd_type == TypeFloat2)
           osl_attr.type = TypeFloat2;
+        else if (req.subd_type == TypeRGBA)
+          osl_attr.type = TypeRGBA;
         else
           osl_attr.type = TypeDesc::TypeColor;
 
@@ -1341,6 +1347,8 @@ void MeshManager::update_svm_attributes(Device *,
           attr_map[index].w = NODE_ATTR_MATRIX;
         else if (req.triangle_type == TypeFloat2)
           attr_map[index].w = NODE_ATTR_FLOAT2;
+        else if (req.triangle_type == TypeRGBA)
+          attr_map[index].w = NODE_ATTR_RGBA;
         else
           attr_map[index].w = NODE_ATTR_FLOAT3;
 
@@ -1379,6 +1387,8 @@ void MeshManager::update_svm_attributes(Device *,
           attr_map[index].w = NODE_ATTR_MATRIX;
         else if (req.subd_type == TypeFloat2)
           attr_map[index].w = NODE_ATTR_FLOAT2;
+        else if (req.triangle_type == TypeRGBA)
+          attr_map[index].w = NODE_ATTR_RGBA;
         else
           attr_map[index].w = NODE_ATTR_FLOAT3;
 
index 1d98fabbc9f9dc14faf715a6588b9ea5524986de..71f1863ea494ed4e333da6aebe7bf5f3cbb150b9 100644 (file)
@@ -4342,6 +4342,64 @@ void VolumeInfoNode::compile(OSLCompiler &)
 {
 }
 
+NODE_DEFINE(VertexColorNode)
+{
+  NodeType *type = NodeType::add("vertex_color", create, NodeType::SHADER);
+
+  SOCKET_STRING(layer_name, "Layer Name", ustring());
+  SOCKET_OUT_COLOR(color, "Color");
+  SOCKET_OUT_FLOAT(alpha, "Alpha");
+
+  return type;
+}
+
+VertexColorNode::VertexColorNode() : ShaderNode(node_type)
+{
+}
+
+void VertexColorNode::attributes(Shader *shader, AttributeRequestSet *attributes)
+{
+  if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) {
+    attributes->add_standard(layer_name);
+  }
+  ShaderNode::attributes(shader, attributes);
+}
+
+void VertexColorNode::compile(SVMCompiler &compiler)
+{
+  ShaderOutput *color_out = output("Color");
+  ShaderOutput *alpha_out = output("Alpha");
+  int layer_id = compiler.attribute(layer_name);
+
+  ShaderNodeType node;
+
+  if (bump == SHADER_BUMP_DX)
+    node = NODE_VERTEX_COLOR_BUMP_DX;
+  else if (bump == SHADER_BUMP_DY)
+    node = NODE_VERTEX_COLOR_BUMP_DY;
+  else {
+    node = NODE_VERTEX_COLOR;
+  }
+
+  compiler.add_node(
+      node, layer_id, compiler.stack_assign(color_out), compiler.stack_assign(alpha_out));
+}
+
+void VertexColorNode::compile(OSLCompiler &compiler)
+{
+  if (bump == SHADER_BUMP_DX) {
+    compiler.parameter("bump_offset", "dx");
+  }
+  else if (bump == SHADER_BUMP_DY) {
+    compiler.parameter("bump_offset", "dy");
+  }
+  else {
+    compiler.parameter("bump_offset", "center");
+  }
+  compiler.parameter("layer_name", layer_name.c_str());
+  compiler.add(this, "node_vertex_color");
+}
+
 /* Value */
 
 NODE_DEFINE(ValueNode)
index 171568644fb45a59cc6e4e78f45ee70477ace32e..13e9b65fa074cdf89b6da48001fff8f4b02f72a6 100644 (file)
@@ -979,6 +979,22 @@ class VolumeInfoNode : public ShaderNode {
   void expand(ShaderGraph *graph);
 };
 
+class VertexColorNode : public ShaderNode {
+ public:
+  SHADER_NODE_CLASS(VertexColorNode)
+  void attributes(Shader *shader, AttributeRequestSet *attributes);
+  bool has_attribute_dependency()
+  {
+    return true;
+  }
+  bool has_spatial_varying()
+  {
+    return true;
+  }
+
+  ustring layer_name;
+};
+
 class ValueNode : public ShaderNode {
  public:
   SHADER_NODE_CLASS(ValueNode)
index 6e61190de6b11b2e8d5c0353de38595dbb852b36..c6937ca78feaac23f5f881ae986cf7bc5bc2ff08 100644 (file)
@@ -43,11 +43,29 @@ ccl_device uchar4 color_float_to_byte(float3 c)
   return make_uchar4(r, g, b, 0);
 }
 
+ccl_device uchar4 color_float4_to_uchar4(float4 c)
+{
+  uchar r, g, b, a;
+
+  r = float_to_byte(c.x);
+  g = float_to_byte(c.y);
+  b = float_to_byte(c.z);
+  a = float_to_byte(c.w);
+
+  return make_uchar4(r, g, b, a);
+}
+
 ccl_device_inline float3 color_byte_to_float(uchar4 c)
 {
   return make_float3(c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f));
 }
 
+ccl_device_inline float4 color_uchar4_to_float4(uchar4 c)
+{
+  return make_float4(
+      c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f), c.w * (1.0f / 255.0f));
+}
+
 ccl_device float color_srgb_to_linear(float c)
 {
   if (c < 0.04045f)
index cfbe416aba1771e683511f95ae83384273e4680c..3f8e2d6d700dbed8227d5351f329ef29261f1cb6 100644 (file)
@@ -29,6 +29,11 @@ CCL_NAMESPACE_BEGIN
 OIIO_NAMESPACE_USING
 
 static constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2);
+static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR);
+static constexpr TypeDesc TypeFloatArray4(TypeDesc::FLOAT,
+                                          TypeDesc::SCALAR,
+                                          TypeDesc::NOSEMANTICS,
+                                          4);
 
 CCL_NAMESPACE_END
 
index 5dc2cf8d106023b2b5735e6c40e65bb1737c07dd..f0f1baba642efc34ea6c4f808f08e01dc0138e9f 100644 (file)
@@ -190,6 +190,7 @@ shader_node_categories = [
         NodeItem("ShaderNodeParticleInfo"),
         NodeItem("ShaderNodeCameraData"),
         NodeItem("ShaderNodeUVMap"),
+        NodeItem("ShaderNodeVertexColor"),
         NodeItem("ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll),
         NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
     ]),
index 98710394079545a04d384c9f394f68ca014412dd..f88aebd312ce5cfa1db0a5b0b81c2717a2004f01 100644 (file)
@@ -978,6 +978,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
 #define SH_NODE_CLAMP 703
 #define SH_NODE_TEX_WHITE_NOISE 704
 #define SH_NODE_VOLUME_INFO 705
+#define SH_NODE_VERTEX_COLOR 706
 
 /* custom defines options for Material node */
 #define SH_NODE_MAT_DIFF 1
index c5e16b2d3cd1df30d0211131ba70823dd966fc17..6e45130ce443d339b6fec6379ecdc347c3d9f31e 100644 (file)
@@ -3914,6 +3914,7 @@ static void registerShaderNodes(void)
   register_node_type_sh_tex_coord();
   register_node_type_sh_particle_info();
   register_node_type_sh_bump();
+  register_node_type_sh_vertex_color();
 
   register_node_type_sh_background();
   register_node_type_sh_bsdf_anisotropic();
index 6055a503b7bafcfe68530d3b03e9be4cba1dab25..8a4cbb3c71a8166aa8dd2f1d1113951dc9e888fc 100644 (file)
@@ -998,6 +998,18 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt
   }
 }
 
+static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+  PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
+  if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
+    PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
+    uiItemPointerR(layout, ptr, "layer_name", &dataptr, "vertex_colors", "", ICON_GROUP_VCOL);
+  }
+  else {
+    uiItemL(layout, "No mesh in active object.", ICON_ERROR);
+  }
+}
+
 static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
   uiItemR(layout, ptr, "use_tips", 0, NULL, 0);
@@ -1299,6 +1311,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
     case SH_NODE_UVMAP:
       ntype->draw_buttons = node_shader_buts_uvmap;
       break;
+    case SH_NODE_VERTEX_COLOR:
+      ntype->draw_buttons = node_shader_buts_vertex_color;
+      break;
     case SH_NODE_UVALONGSTROKE:
       ntype->draw_buttons = node_shader_buts_uvalongstroke;
       break;
index aea96dac2e3b5569df95a895564b72315b3bbebb..8d2355ff5aced87ec42e9ab2741441090a7ed744 100644 (file)
@@ -313,6 +313,7 @@ data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_vertex_color.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_volume_info.glsl SRC)
 data_to_c_simple(shaders/material/gpu_shader_material_volume_principled.glsl SRC)
index 8b68bcd58890ebbb5062b5113fd9ac28f84ceaa0..242b0ed2e31f2a431c75eb6ced497bd0cd977282 100644 (file)
@@ -1080,6 +1080,15 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
                     "\treturn mix(c1, c2, step(vec3(0.04045), c));\n"
                     "}\n\n");
 
+  BLI_dynstr_append(ds,
+                    "vec4 srgba_to_linear_attr(vec4 c) {\n"
+                    "\tc = max(c, vec4(0.0));\n"
+                    "\tvec4 c1 = c * (1.0 / 12.92);\n"
+                    "\tvec4 c2 = pow((c + 0.055) * (1.0 / 1.055), vec4(2.4));\n"
+                    "\tvec4 final = mix(c1, c2, step(vec4(0.04045), c));"
+                    "\treturn vec4(final.xyz, c.a);\n"
+                    "}\n\n");
+
   /* Prototype because defined later. */
   BLI_dynstr_append(ds,
                     "vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
@@ -1184,7 +1193,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
         }
         else if (input->attr_type == CD_MCOL) {
           BLI_dynstr_appendf(ds,
-                             "\tvar%d%s = srgb_to_linear_attr(att%d);\n",
+                             "\tvar%d%s = srgba_to_linear_attr(att%d);\n",
                              input->attr_id,
                              use_geom ? "g" : "",
                              input->attr_id);
index 06544d27af94aaba676bb2f0929261a76d05a224..3a38eb5c600c7962049a331cbee2108cca01794d 100644 (file)
@@ -114,6 +114,7 @@ extern char datatoc_gpu_shader_material_vector_curves_glsl[];
 extern char datatoc_gpu_shader_material_vector_displacement_glsl[];
 extern char datatoc_gpu_shader_material_vector_math_glsl[];
 extern char datatoc_gpu_shader_material_velvet_glsl[];
+extern char datatoc_gpu_shader_material_vertex_color_glsl[];
 extern char datatoc_gpu_shader_material_volume_absorption_glsl[];
 extern char datatoc_gpu_shader_material_volume_info_glsl[];
 extern char datatoc_gpu_shader_material_volume_principled_glsl[];
@@ -527,6 +528,11 @@ static GPUMaterialLibrary gpu_shader_material_velvet_library = {
     .dependencies = {&gpu_shader_material_diffuse_library, NULL},
 };
 
+static GPUMaterialLibrary gpu_shader_material_vertex_color_library = {
+    .code = datatoc_gpu_shader_material_vertex_color_glsl,
+    .dependencies = {NULL},
+};
+
 static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = {
     .code = datatoc_gpu_shader_material_volume_absorption_glsl,
     .dependencies = {NULL},
@@ -638,6 +644,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
     &gpu_shader_material_vector_displacement_library,
     &gpu_shader_material_vector_math_library,
     &gpu_shader_material_velvet_library,
+    &gpu_shader_material_vertex_color_library,
     &gpu_shader_material_volume_absorption_library,
     &gpu_shader_material_volume_info_library,
     &gpu_shader_material_volume_principled_library,
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl
new file mode 100644 (file)
index 0000000..551b838
--- /dev/null
@@ -0,0 +1,5 @@
+void node_vertex_color(vec4 vertexColor, out vec4 outColor, out float outAlpha)
+{
+  outColor = vertexColor;
+  outAlpha = vertexColor.a;
+}
index 6b46c5887b43e1e7322997efb22e9df659f0d53a..0287a1510fee24b544480c2a2d9601bd15d26016 100644 (file)
@@ -997,6 +997,10 @@ typedef struct NodeShaderUVMap {
   char uv_map[64];
 } NodeShaderUVMap;
 
+typedef struct NodeShaderVertexColor {
+  char layer_name[64];
+} NodeShaderVertexColor;
+
 typedef struct NodeShaderTexIES {
   int mode;
 
index 3d90d5663156be451c41af4e28c5b252b0cef9ac..913324e4997a0d7e0ba57599aa9e56e1c17ea8ea 100644 (file)
@@ -4867,6 +4867,19 @@ static void def_sh_uvmap(StructRNA *srna)
   RNA_def_struct_sdna_from(srna, "bNode", NULL);
 }
 
+static void def_sh_vertex_color(StructRNA *srna)
+{
+  PropertyRNA *prop;
+
+  RNA_def_struct_sdna_from(srna, "NodeShaderVertexColor", "storage");
+
+  prop = RNA_def_property(srna, "layer_name", PROP_STRING, PROP_NONE);
+  RNA_def_property_ui_text(prop, "Vertex Color", "Vertex Color");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+  RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
 static void def_sh_uvalongstroke(StructRNA *srna)
 {
   PropertyRNA *prop;
index ea2968f49172533186ae2c506c938e708a73b9e5..57a4ace997c6f02f2806e982132e440bd33b0231 100644 (file)
@@ -206,6 +206,7 @@ set(SRC
   shader/nodes/node_shader_valToRgb.c
   shader/nodes/node_shader_value.c
   shader/nodes/node_shader_vectTransform.c
+  shader/nodes/node_shader_vertex_color.c
   shader/nodes/node_shader_vector_displacement.c
   shader/nodes/node_shader_vector_math.c
   shader/nodes/node_shader_volume_absorption.c
index 30673e7cd31ae9091c78fc327a086d0d09cf6158..a004090d03d402dd5b4082c67dfa494cb281d489 100644 (file)
@@ -86,6 +86,7 @@ void register_node_type_sh_script(void);
 void register_node_type_sh_normal_map(void);
 void register_node_type_sh_tangent(void);
 void register_node_type_sh_vect_transform(void);
+void register_node_type_sh_vertex_color(void);
 
 void register_node_type_sh_ambient_occlusion(void);
 void register_node_type_sh_background(void);
index d14511504f01dae846890d6d97d2661234f85299..f3bc5a0cafa37ff4cdd07acdf2431ac11ffb2709 100644 (file)
@@ -121,6 +121,7 @@ DefNode(ShaderNode,     SH_NODE_VECT_TRANSFORM,     def_sh_vect_transform,  "VEC
 DefNode(ShaderNode,     SH_NODE_SEPHSV,             0,                      "SEPHSV",             SeparateHSV,      "Separate HSV",      ""       )
 DefNode(ShaderNode,     SH_NODE_COMBHSV,            0,                      "COMBHSV",            CombineHSV,       "Combine HSV",       ""       )
 DefNode(ShaderNode,     SH_NODE_UVMAP,              def_sh_uvmap,           "UVMAP",              UVMap,            "UV Map",            ""       )
+DefNode(ShaderNode,     SH_NODE_VERTEX_COLOR,       def_sh_vertex_color,    "VERTEX_COLOR",       VertexColor,      "Vertex Color",      ""       )
 DefNode(ShaderNode,     SH_NODE_UVALONGSTROKE,      def_sh_uvalongstroke,   "UVALONGSTROKE",      UVAlongStroke,    "UV Along Stroke",   ""       )
 DefNode(ShaderNode,     SH_NODE_SEPXYZ,             0,                      "SEPXYZ",             SeparateXYZ,      "Separate XYZ",      ""       )
 DefNode(ShaderNode,     SH_NODE_COMBXYZ,            0,                      "COMBXYZ",            CombineXYZ,       "Combine XYZ",       ""       )
diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
new file mode 100644 (file)
index 0000000..8848fc3
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "../node_shader_util.h"
+
+static bNodeSocketTemplate sh_node_vertex_color_out[] = {
+    {SOCK_RGBA, 0, N_("Color")},
+    {SOCK_FLOAT, 0, N_("Alpha")},
+    {-1, 0, ""},
+};
+
+static void node_shader_init_vertex_color(bNodeTree *UNUSED(ntree), bNode *node)
+{
+  NodeShaderVertexColor *vertexColor = MEM_callocN(sizeof(NodeShaderVertexColor),
+                                                   "NodeShaderVertexColor");
+  node->storage = vertexColor;
+}
+
+static int node_shader_gpu_vertex_color(GPUMaterial *mat,
+                                        bNode *node,
+                                        bNodeExecData *UNUSED(execdata),
+                                        GPUNodeStack *in,
+                                        GPUNodeStack *out)
+{
+  NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
+  GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name);
+  return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
+}
+
+void register_node_type_sh_vertex_color(void)
+{
+  static bNodeType ntype;
+
+  sh_node_type_base(&ntype, SH_NODE_VERTEX_COLOR, "Vertex Color", NODE_CLASS_INPUT, 0);
+  node_type_socket_templates(&ntype, NULL, sh_node_vertex_color_out);
+  node_type_init(&ntype, node_shader_init_vertex_color);
+  node_type_storage(
+      &ntype, "NodeShaderVertexColor", node_free_standard_storage, node_copy_standard_storage);
+  node_type_gpu(&ntype, node_shader_gpu_vertex_color);
+
+  nodeRegisterType(&ntype);
+}