Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2021-12-01 19:30:46 +0300
committerBrecht Van Lommel <brecht@blender.org>2021-12-16 22:54:04 +0300
commit35b1e9fc3acd6db565e7e54252a4a4152d8343d9 (patch)
tree8599df3b2be192d1fe19d30a8afb7e8d8729499e /intern/cycles/bvh/build.cpp
parent2229179faa44e2c685b4eabd0c51d4c7d5c1f193 (diff)
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
Diffstat (limited to 'intern/cycles/bvh/build.cpp')
-rw-r--r--intern/cycles/bvh/build.cpp130
1 files changed, 124 insertions, 6 deletions
diff --git a/intern/cycles/bvh/build.cpp b/intern/cycles/bvh/build.cpp
index 3ce268dfb25..91198e4e2a2 100644
--- a/intern/cycles/bvh/build.cpp
+++ b/intern/cycles/bvh/build.cpp
@@ -26,6 +26,7 @@
#include "scene/hair.h"
#include "scene/mesh.h"
#include "scene/object.h"
+#include "scene/pointcloud.h"
#include "scene/scene.h"
#include "util/algorithm.h"
@@ -113,9 +114,9 @@ void BVHBuild::add_reference_triangles(BoundBox &root,
else {
/* Motion triangles, trace optimized case: we split triangle
* primitives into separate nodes for each of the time steps.
- * This way we minimize overlap of neighbor curve primitives.
+ * This way we minimize overlap of neighbor triangle primitives.
*/
- const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
+ const int num_bvh_steps = params.num_motion_triangle_steps * 2 + 1;
const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
const size_t num_verts = mesh->verts.size();
const size_t num_steps = mesh->motion_steps;
@@ -269,6 +270,101 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
}
}
+void BVHBuild::add_reference_points(BoundBox &root,
+ BoundBox &center,
+ PointCloud *pointcloud,
+ int i)
+{
+ const Attribute *point_attr_mP = NULL;
+ if (pointcloud->has_motion_blur()) {
+ point_attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+
+ const float3 *points_data = &pointcloud->points[0];
+ const float *radius_data = &pointcloud->radius[0];
+ const size_t num_points = pointcloud->num_points();
+ const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL;
+ const size_t num_steps = pointcloud->get_motion_steps();
+
+ if (point_attr_mP == NULL) {
+ /* Really simple logic for static points. */
+ for (uint j = 0; j < num_points; j++) {
+ const PointCloud::Point point = pointcloud->get_point(j);
+ BoundBox bounds = BoundBox::empty;
+ point.bounds_grow(points_data, radius_data, bounds);
+ if (bounds.valid()) {
+ references.push_back(BVHReference(bounds, j, i, PRIMITIVE_POINT));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ }
+ else if (params.num_motion_point_steps == 0 || params.use_spatial_split) {
+ /* Simple case of motion points: single node for the whole
+ * shutter time. Lowest memory usage but less optimal
+ * rendering.
+ */
+ /* TODO(sergey): Support motion steps for spatially split BVH. */
+ for (uint j = 0; j < num_points; j++) {
+ const PointCloud::Point point = pointcloud->get_point(j);
+ BoundBox bounds = BoundBox::empty;
+ point.bounds_grow(points_data, radius_data, bounds);
+ for (size_t step = 0; step < num_steps - 1; step++) {
+ point.bounds_grow(motion_data + step * num_points, radius_data, bounds);
+ }
+ if (bounds.valid()) {
+ references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ }
+ else {
+ /* Motion points, trace optimized case: we split point
+ * primitives into separate nodes for each of the time steps.
+ * This way we minimize overlap of neighbor point primitives.
+ */
+ const int num_bvh_steps = params.num_motion_point_steps * 2 + 1;
+ const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
+
+ for (uint j = 0; j < num_points; j++) {
+ const PointCloud::Point point = pointcloud->get_point(j);
+ const size_t num_steps = pointcloud->get_motion_steps();
+ const float3 *point_steps = point_attr_mP->data_float3();
+
+ /* Calculate bounding box of the previous time step.
+ * Will be reused later to avoid duplicated work on
+ * calculating BVH time step boundbox.
+ */
+ float4 prev_key = point.motion_key(
+ points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j);
+ BoundBox prev_bounds = BoundBox::empty;
+ point.bounds_grow(prev_key, prev_bounds);
+ /* Create all primitive time steps, */
+ for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
+ const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
+ float4 curr_key = point.motion_key(
+ points_data, radius_data, point_steps, num_points, num_steps, curr_time, j);
+ BoundBox curr_bounds = BoundBox::empty;
+ point.bounds_grow(curr_key, curr_bounds);
+ BoundBox bounds = prev_bounds;
+ bounds.grow(curr_bounds);
+ if (bounds.valid()) {
+ const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
+ references.push_back(
+ BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT, prev_time, curr_time));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ /* Current time boundbox becomes previous one for the
+ * next time step.
+ */
+ prev_bounds = curr_bounds;
+ }
+ }
+ }
+}
+
void BVHBuild::add_reference_geometry(BoundBox &root,
BoundBox &center,
Geometry *geom,
@@ -282,6 +378,10 @@ void BVHBuild::add_reference_geometry(BoundBox &root,
Hair *hair = static_cast<Hair *>(geom);
add_reference_curves(root, center, hair, object_index);
}
+ else if (geom->geometry_type == Geometry::POINTCLOUD) {
+ PointCloud *pointcloud = static_cast<PointCloud *>(geom);
+ add_reference_points(root, center, pointcloud, object_index);
+ }
}
void BVHBuild::add_reference_object(BoundBox &root, BoundBox &center, Object *ob, int i)
@@ -311,6 +411,10 @@ static size_t count_primitives(Geometry *geom)
Hair *hair = static_cast<Hair *>(geom);
return count_curve_segments(hair);
}
+ else if (geom->geometry_type == Geometry::POINTCLOUD) {
+ PointCloud *pointcloud = static_cast<PointCloud *>(geom);
+ return pointcloud->num_points();
+ }
return 0;
}
@@ -328,8 +432,9 @@ void BVHBuild::add_references(BVHRange &root)
if (!ob->get_geometry()->is_instanced()) {
num_alloc_references += count_primitives(ob->get_geometry());
}
- else
+ else {
num_alloc_references++;
+ }
}
else {
num_alloc_references += count_primitives(ob->get_geometry());
@@ -394,7 +499,7 @@ BVHNode *BVHBuild::run()
spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
spatial_free_index = 0;
- need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0;
+ need_prim_time = params.use_motion_steps();
/* init progress updates */
double build_start_time;
@@ -535,7 +640,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
const vector<BVHReference> &references) const
{
size_t size = range.size();
- size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size);
+ size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size),
+ params.max_point_leaf_size);
if (size > max_leaf_size)
return false;
@@ -544,6 +650,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
size_t num_motion_triangles = 0;
size_t num_curves = 0;
size_t num_motion_curves = 0;
+ size_t num_points = 0;
+ size_t num_motion_points = 0;
for (int i = 0; i < size; i++) {
const BVHReference &ref = references[range.start() + i];
@@ -564,12 +672,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
num_triangles++;
}
}
+ else if (ref.prim_type() & PRIMITIVE_ALL_POINT) {
+ if (ref.prim_type() & PRIMITIVE_ALL_MOTION) {
+ num_motion_points++;
+ }
+ else {
+ num_points++;
+ }
+ }
}
return (num_triangles <= params.max_triangle_leaf_size) &&
(num_motion_triangles <= params.max_motion_triangle_leaf_size) &&
(num_curves <= params.max_curve_leaf_size) &&
- (num_motion_curves <= params.max_motion_curve_leaf_size);
+ (num_motion_curves <= params.max_motion_curve_leaf_size) &&
+ (num_points <= params.max_point_leaf_size) &&
+ (num_motion_points <= params.max_motion_point_leaf_size);
}
/* multithreaded binning builder */