[Bf-blender-cvs] [35b1e9fc3ac] master: Cycles: pointcloud rendering

Brecht Van Lommel noreply at git.blender.org
Thu Dec 16 21:03:12 CET 2021


Commit: 35b1e9fc3acd6db565e7e54252a4a4152d8343d9
Author: Brecht Van Lommel
Date:   Wed Dec 1 17:30:46 2021 +0100
Branches: master
https://developer.blender.org/rB35b1e9fc3acd6db565e7e54252a4a4152d8343d9

Cycles: pointcloud rendering

This add support for rendering of the point cloud object in Blender, as a native
geometry type in Cycles that is more memory and time efficient than instancing
sphere meshes. This can be useful for rendering sand, water splashes, particles,
motion graphics, etc.

Points are currently always rendered as spheres, with backface culling. More
shapes are likely to be added later, but this is the most important one and can
be customized with shaders.

For CPU rendering the Embree primitive is used, for GPU there is our own
intersection code. Motion blur is suppored. Volumes inside points are not
currently supported.

Implemented with help from:
* Kévin Dietrich: Alembic procedural integration
* Patrick Mourse: OptiX integration
* Josh Whelchel: update for cycles-x changes

Ref T92573

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

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

M	intern/cycles/blender/CMakeLists.txt
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/geometry.cpp
M	intern/cycles/blender/object.cpp
A	intern/cycles/blender/pointcloud.cpp
M	intern/cycles/blender/sync.h
M	intern/cycles/bvh/build.cpp
M	intern/cycles/bvh/build.h
M	intern/cycles/bvh/bvh2.cpp
M	intern/cycles/bvh/embree.cpp
M	intern/cycles/bvh/embree.h
M	intern/cycles/bvh/params.h
M	intern/cycles/bvh/split.cpp
M	intern/cycles/bvh/split.h
M	intern/cycles/device/optix/device_impl.cpp
M	intern/cycles/device/optix/device_impl.h
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/bvh/bvh.h
M	intern/cycles/kernel/bvh/shadow_all.h
M	intern/cycles/kernel/bvh/traversal.h
M	intern/cycles/kernel/bvh/types.h
M	intern/cycles/kernel/bvh/util.h
M	intern/cycles/kernel/device/optix/kernel.cu
M	intern/cycles/kernel/geom/geom.h
A	intern/cycles/kernel/geom/motion_point.h
A	intern/cycles/kernel/geom/point.h
A	intern/cycles/kernel/geom/point_intersect.h
M	intern/cycles/kernel/geom/primitive.h
M	intern/cycles/kernel/geom/shader_data.h
M	intern/cycles/kernel/osl/services.cpp
M	intern/cycles/kernel/osl/services.h
M	intern/cycles/kernel/svm/wireframe.h
M	intern/cycles/kernel/textures.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/CMakeLists.txt
M	intern/cycles/scene/alembic.cpp
M	intern/cycles/scene/alembic.h
M	intern/cycles/scene/alembic_read.cpp
M	intern/cycles/scene/alembic_read.h
M	intern/cycles/scene/attribute.cpp
M	intern/cycles/scene/geometry.cpp
M	intern/cycles/scene/geometry.h
M	intern/cycles/scene/object.cpp
A	intern/cycles/scene/pointcloud.cpp
A	intern/cycles/scene/pointcloud.h
M	intern/cycles/scene/scene.cpp
M	intern/cycles/scene/scene.h
M	tests/python/CMakeLists.txt

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

diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 1f05b1aa234..fe7d0b89bb0 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
   object_cull.cpp
   output_driver.cpp
   particles.cpp
+  pointcloud.cpp
   curves.cpp
   logging.cpp
   python.cpp
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index fd86d75a301..e4fbc898070 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1020,7 +1020,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
     def poll(cls, context):
         ob = context.object
         if CyclesButtonsPanel.poll(context) and ob:
-            if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}:
+            if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'HAIR', 'POINTCLOUD'}:
                 return True
             if ob.instance_type == 'COLLECTION' and ob.instance_collection:
                 return True
diff --git a/intern/cycles/blender/geometry.cpp b/intern/cycles/blender/geometry.cpp
index a5f36a3a17d..78c803b7adb 100644
--- a/intern/cycles/blender/geometry.cpp
+++ b/intern/cycles/blender/geometry.cpp
@@ -19,6 +19,7 @@
 #include "scene/hair.h"
 #include "scene/mesh.h"
 #include "scene/object.h"
+#include "scene/pointcloud.h"
 #include "scene/volume.h"
 
 #include "blender/sync.h"
@@ -39,6 +40,10 @@ static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_parti
     return Geometry::HAIR;
   }
 
+  if (b_ob_info.object_data.is_a(&RNA_PointCloud)) {
+    return Geometry::POINTCLOUD;
+  }
+
   if (b_ob_info.object_data.is_a(&RNA_Volume) ||
       (b_ob_info.object_data == b_ob_info.real_object.data() &&
        object_fluid_gas_domain_find(b_ob_info.real_object))) {
@@ -111,6 +116,9 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
     else if (geom_type == Geometry::VOLUME) {
       geom = scene->create_node<Volume>();
     }
+    else if (geom_type == Geometry::POINTCLOUD) {
+      geom = scene->create_node<PointCloud>();
+    }
     else {
       geom = scene->create_node<Mesh>();
     }
@@ -170,6 +178,10 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
       Volume *volume = static_cast<Volume *>(geom);
       sync_volume(b_ob_info, volume);
     }
+    else if (geom_type == Geometry::POINTCLOUD) {
+      PointCloud *pointcloud = static_cast<PointCloud *>(geom);
+      sync_pointcloud(pointcloud, b_ob_info);
+    }
     else {
       Mesh *mesh = static_cast<Mesh *>(geom);
       sync_mesh(b_depsgraph, b_ob_info, mesh);
@@ -231,6 +243,10 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
              object_fluid_gas_domain_find(b_ob_info.real_object)) {
       /* No volume motion blur support yet. */
     }
+    else if (b_ob_info.object_data.is_a(&RNA_PointCloud)) {
+      PointCloud *pointcloud = static_cast<PointCloud *>(geom);
+      sync_pointcloud_motion(pointcloud, b_ob_info, motion_step);
+    }
     else {
       Mesh *mesh = static_cast<Mesh *>(geom);
       sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step);
diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp
index d6c52f7faf9..86314d3b196 100644
--- a/intern/cycles/blender/object.cpp
+++ b/intern/cycles/blender/object.cpp
@@ -72,7 +72,8 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
 
   BL::Object::type_enum type = b_ob_info.iter_object.type();
 
-  if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) {
+  if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR ||
+      type == BL::Object::type_POINTCLOUD) {
     /* Will be exported attached to mesh. */
     return true;
   }
@@ -206,7 +207,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
     return NULL;
   }
 
-  /* only interested in object that we can create meshes from */
+  /* only interested in object that we can create geometry from */
   if (!object_is_geometry(b_ob_info)) {
     return NULL;
   }
diff --git a/intern/cycles/blender/pointcloud.cpp b/intern/cycles/blender/pointcloud.cpp
new file mode 100644
index 00000000000..a9e616a468f
--- /dev/null
+++ b/intern/cycles/blender/pointcloud.cpp
@@ -0,0 +1,253 @@
+/*
+ * 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 "scene/pointcloud.h"
+#include "scene/attribute.h"
+#include "scene/scene.h"
+
+#include "blender/sync.h"
+#include "blender/util.h"
+
+#include "util/foreach.h"
+#include "util/hash.h"
+
+CCL_NAMESPACE_BEGIN
+
+template<typename TypeInCycles, typename GetValueAtIndex>
+static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
+                                   TypeInCycles *data,
+                                   const GetValueAtIndex &get_value_at_index)
+{
+  const int num_points = b_pointcloud.points.length();
+  for (int i = 0; i < num_points; i++) {
+    data[i] = get_value_at_index(i);
+  }
+}
+
+static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud)
+{
+  AttributeSet &attributes = pointcloud->attributes;
+  for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
+    const ustring name{b_attribute.name().c_str()};
+
+    if (attributes.find(name)) {
+      continue;
+    }
+
+    const AttributeElement element = ATTR_ELEMENT_VERTEX;
+    const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type();
+    switch (b_data_type) {
+      case BL::Attribute::data_type_FLOAT: {
+        BL::FloatAttribute b_float_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeFloat, element);
+        float *data = attr->data_float();
+        fill_generic_attribute(
+            b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); });
+        break;
+      }
+      case BL::Attribute::data_type_BOOLEAN: {
+        BL::BoolAttribute b_bool_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeFloat, element);
+        float *data = attr->data_float();
+        fill_generic_attribute(
+            b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); });
+        break;
+      }
+      case BL::Attribute::data_type_INT: {
+        BL::IntAttribute b_int_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeFloat, element);
+        float *data = attr->data_float();
+        fill_generic_attribute(
+            b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); });
+        break;
+      }
+      case BL::Attribute::data_type_FLOAT_VECTOR: {
+        BL::FloatVectorAttribute b_vector_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeVector, element);
+        float3 *data = attr->data_float3();
+        fill_generic_attribute(b_pointcloud, data, [&](int i) {
+          BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
+          return make_float3(v[0], v[1], v[2]);
+        });
+        break;
+      }
+      case BL::Attribute::data_type_FLOAT_COLOR: {
+        BL::FloatColorAttribute b_color_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeRGBA, element);
+        float4 *data = attr->data_float4();
+        fill_generic_attribute(b_pointcloud, data, [&](int i) {
+          BL::Array<float, 4> v = b_color_attribute.data[i].color();
+          return make_float4(v[0], v[1], v[2], v[3]);
+        });
+        break;
+      }
+      case BL::Attribute::data_type_FLOAT2: {
+        BL::Float2Attribute b_float2_attribute{b_attribute};
+        Attribute *attr = attributes.add(name, TypeFloat2, element);
+        float2 *data = attr->data_float2();
+        fill_generic_attribute(b_pointcloud, data, [&](int i) {
+          BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
+          return make_float2(v[0], v[1]);
+        });
+        break;
+      }
+      default:
+        /* Not supported. */
+        break;
+    }
+  }
+}
+
+static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud)
+{
+  /* TODO: optimize so we can straight memcpy arrays from Blender? */
+
+  /* Add requested attributes. */
+  Attribute *attr_random = NULL;
+  if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
+    attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
+  }
+
+  /* Reserve memory. */
+  const int num_points = b_pointcloud.points.length();
+  pointcloud->reserve(num_points);
+
+  /* Export points. */
+  BL::PointCloud::points_iterator b_point_iter;
+  for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end();
+       ++b_point_iter) {
+    BL::Point b_point = *b_point_iter;
+    const float3 co = get_float3(b_point.co());
+    const float radius = b_point.radius();
+    pointcloud->add_point(co, radius);
+
+    /* Random number per point. */
+    if (attr_random != NULL) {
+      attr_random->add(hash_uint2_to_float(b_point.index(), 0));
+    }
+  }
+
+  /* Export attributes */
+  copy_attributes(pointcloud, b_pointcloud);
+}
+
+static void export_pointcloud_motion(PointCloud *pointcloud,
+                                     BL::PointCloud b_pointcloud,
+                                     int motion_step)
+{
+  /* Find or add attribute. */
+  Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+  bool new_attribute = false;
+
+  if (!attr_mP) {
+    attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+    new_attribute = true;
+  }
+
+  /* Export motion poin

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list