[Bf-blender-cvs] [7377d411b47] master: Cycles volume: fast empty space optimization by generating a tight mesh around the volume.

Kévin Dietrich noreply at git.blender.org
Thu Mar 1 11:54:42 CET 2018


Commit: 7377d411b47d50cd943cd33e3e55c0409bb79f91
Author: Kévin Dietrich
Date:   Thu Mar 1 11:54:01 2018 +0100
Branches: master
https://developer.blender.org/rB7377d411b47d50cd943cd33e3e55c0409bb79f91

Cycles volume: fast empty space optimization by generating a tight mesh
around the volume.

We generate a tight mesh around the active voxels of the volume in order
to effectively skip empty space, and start volume ray marching as close
to interesting volume data as possible. See code comments for details on
how the mesh generation algorithm works.

This gives up to 2x speedups in some scenes.

Reviewed by: brecht, dingto

Reviewers: #cycles

Subscribers: lvxejay, jtheninja, brecht

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

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

M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/render/CMakeLists.txt
M	intern/cycles/render/attribute.cpp
M	intern/cycles/render/attribute.h
M	intern/cycles/render/image.cpp
M	intern/cycles/render/image.h
M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/mesh.h
A	intern/cycles/render/mesh_volume.cpp
M	intern/cycles/render/scene.cpp
M	intern/cycles/util/util_math_int3.h

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

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 42ceb4d5c8e..998390e92a9 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -335,6 +335,8 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
 	if(!b_domain)
 		return;
 
+	mesh->volume_isovalue = b_domain.clipping();
+
 	Attribute *attr = mesh->attributes.add(std);
 	VoxelAttribute *volume_data = attr->data_voxel();
 	ImageMetaData metadata;
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 580d76e7777..b7248354abd 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -23,6 +23,7 @@ set(SRC
 	mesh.cpp
 	mesh_displace.cpp
 	mesh_subdivision.cpp
+	mesh_volume.cpp
 	nodes.cpp
 	object.cpp
 	osl.cpp
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 6816f8ca3f3..8c77687d9cc 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -535,9 +535,23 @@ void AttributeSet::resize(bool reserve_only)
 	}
 }
 
-void AttributeSet::clear()
+void AttributeSet::clear(bool preserve_voxel_data)
 {
-	attributes.clear();
+	if(preserve_voxel_data) {
+		list<Attribute>::iterator it;
+
+		for(it = attributes.begin(); it != attributes.end();) {
+			if(it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
+				it++;
+			}
+			else {
+				attributes.erase(it++);
+			}
+		}
+	}
+	else {
+		attributes.clear();
+	}
 }
 
 /* AttributeRequest */
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index 9e23345675d..5cb6c75aab2 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -123,7 +123,7 @@ public:
 	void remove(Attribute *attribute);
 
 	void resize(bool reserve_only = false);
-	void clear();
+	void clear(bool preserve_voxel_data = false);
 };
 
 /* AttributeRequest
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index de46599e1db..9c5e32e8219 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -84,6 +84,16 @@ bool ImageManager::set_animation_frame_update(int frame)
 	return false;
 }
 
+device_memory *ImageManager::image_memory(int flat_slot)
+{
+	   ImageDataType type;
+	   int slot = flattened_slot_to_type_index(flat_slot, &type);
+
+	   Image *img = images[type][slot];
+
+	   return img->mem;
+}
+
 bool ImageManager::get_image_metadata(const string& filename,
                                       void *builtin_data,
                                       ImageMetaData& metadata)
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 989416e089a..5391490d993 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -85,6 +85,8 @@ public:
 	void set_osl_texture_system(void *texture_system);
 	bool set_animation_frame_update(int frame);
 
+	device_memory *image_memory(int flat_slot);
+
 	bool need_update;
 
 	/* NOTE: Here pixels_size is a size of storage, which equals to
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 5bcb47deb65..23b855acdc9 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -446,6 +446,7 @@ Mesh::Mesh()
 
 	geometry_flags = GEOMETRY_NONE;
 
+	volume_isovalue = 0.001f;
 	has_volume = false;
 	has_surface_bssrdf = false;
 
@@ -533,7 +534,7 @@ void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
 	subd_attributes.resize(true);
 }
 
-void Mesh::clear()
+void Mesh::clear(bool preserve_voxel_data)
 {
 	/* clear all verts and triangles */
 	verts.clear();
@@ -556,15 +557,18 @@ void Mesh::clear()
 
 	subd_creases.clear();
 
-	attributes.clear();
 	curve_attributes.clear();
 	subd_attributes.clear();
-	used_shaders.clear();
+	attributes.clear(preserve_voxel_data);
+
+	if(!preserve_voxel_data) {
+		used_shaders.clear();
+		geometry_flags = GEOMETRY_NONE;
+	}
 
 	transform_applied = false;
 	transform_negative_scaled = false;
 	transform_normal = transform_identity();
-	geometry_flags = GEOMETRY_NONE;
 
 	delete patch_table;
 	patch_table = NULL;
@@ -1892,17 +1896,22 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
 	delete bvh;
 }
 
-void MeshManager::device_update_flags(Device * /*device*/,
-                                      DeviceScene * /*dscene*/,
-                                      Scene * scene,
-                                      Progress& /*progress*/)
+void MeshManager::device_update_preprocess(Device *device,
+                                           Scene *scene,
+                                           Progress& progress)
 {
 	if(!need_update && !need_flags_update) {
 		return;
 	}
-	/* update flags */
+
+	progress.set_status("Updating Meshes Flags");
+
+	/* Update flags. */
+	bool volume_images_updated = false;
+
 	foreach(Mesh *mesh, scene->meshes) {
 		mesh->has_volume = false;
+
 		foreach(const Shader *shader, mesh->used_shaders) {
 			if(shader->has_volume) {
 				mesh->has_volume = true;
@@ -1911,7 +1920,29 @@ void MeshManager::device_update_flags(Device * /*device*/,
 				mesh->has_surface_bssrdf = true;
 			}
 		}
+
+		if(need_update && mesh->has_volume) {
+			/* Create volume meshes if there is voxel data. */
+			bool has_voxel_attributes = false;
+
+			foreach(Attribute& attr, mesh->attributes.attributes) {
+				if(attr.element == ATTR_ELEMENT_VOXEL) {
+					has_voxel_attributes = true;
+				}
+			}
+
+			if(has_voxel_attributes) {
+				if(!volume_images_updated) {
+					progress.set_status("Updating Meshes Volume Bounds");
+					device_update_volume_images(device, scene, progress);
+					volume_images_updated = true;
+				}
+
+				create_volume_mesh(scene, mesh, progress);
+			}
+		}
 	}
+
 	need_flags_update = false;
 }
 
@@ -1954,6 +1985,44 @@ void MeshManager::device_update_displacement_images(Device *device,
 	pool.wait_work();
 }
 
+void MeshManager::device_update_volume_images(Device *device,
+											  Scene *scene,
+											  Progress& progress)
+{
+	progress.set_status("Updating Volume Images");
+	TaskPool pool;
+	ImageManager *image_manager = scene->image_manager;
+	set<int> volume_images;
+
+	foreach(Mesh *mesh, scene->meshes) {
+		if(!mesh->need_update) {
+			continue;
+		}
+
+		foreach(Attribute& attr, mesh->attributes.attributes) {
+			if(attr.element != ATTR_ELEMENT_VOXEL) {
+				continue;
+			}
+
+			VoxelAttribute *voxel = attr.data_voxel();
+
+			if(voxel->slot != -1) {
+				volume_images.insert(voxel->slot);
+			}
+		}
+	}
+
+	foreach(int slot, volume_images) {
+		pool.push(function_bind(&ImageManager::device_update_slot,
+								image_manager,
+								device,
+								scene,
+								slot,
+								&progress));
+	}
+	pool.wait_work();
+}
+
 void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
 {
 	if(!need_update)
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 07d8bbdbf31..c0d1513bee0 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -202,7 +202,8 @@ public:
 	array<int> triangle_patch; /* must be < 0 for non subd triangles */
 	array<float2> vert_patch_uv;
 
-	bool has_volume;  /* Set in the device_update_flags(). */
+	float volume_isovalue;
+	bool has_volume;          /* Set in the device_update_flags(). */
 	bool has_surface_bssrdf;  /* Set in the device_update_flags(). */
 
 	array<float3> curve_keys;
@@ -264,7 +265,7 @@ public:
 	void reserve_curves(int numcurves, int numkeys);
 	void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
 	void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
-	void clear();
+	void clear(bool preserve_voxel_data = false);
 	void add_vertex(float3 P);
 	void add_vertex_slow(float3 P);
 	void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
@@ -335,13 +336,15 @@ public:
 	void update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
 	void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
 
+	void device_update_preprocess(Device *device, Scene *scene, Progress& progress);
 	void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
-	void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
 
 	void device_free(Device *device, DeviceScene *dscene);
 
 	void tag_update(Scene *scene);
 
+	void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
+
 protected:
 	/* Calculate verts/triangles/curves offsets in global arrays. */
 	void mesh_calc_offset(Scene *scene);
@@ -370,6 +373,10 @@ protected:
 	void device_update_displacement_images(Device *device,
 	                                       Scene *scene,
 	                                       Progress& progress);
+
+	void device_update_volume_images(Device *device,
+									 Scene *scene,
+									 Progress& progress);
 };
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
new file mode 100644
index 00000000000..be43154fd93
--- /dev/null
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2011-2016 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 "render/mesh.h"
+#include "render/attribute.h"
+#include "render/scene.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
+#include "util/util_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+static size_t compute_voxel_index(const int3 &r

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list