diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2018-03-01 13:54:01 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2018-03-01 13:54:01 +0300 |
commit | 7377d411b47d50cd943cd33e3e55c0409bb79f91 (patch) | |
tree | e623f792356d08ea03dd37b28de0b57a1695b3af /intern/cycles/render/mesh.cpp | |
parent | 172614fb7dac799d373e778a541e8d9f78228221 (diff) |
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
Diffstat (limited to 'intern/cycles/render/mesh.cpp')
-rw-r--r-- | intern/cycles/render/mesh.cpp | 87 |
1 files changed, 78 insertions, 9 deletions
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) |