diff options
author | Brecht Van Lommel <brecht> | 2020-03-07 16:38:52 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2020-03-18 13:23:05 +0300 |
commit | 1162ba206dd7792414d3ae716877ba1383de8dab (patch) | |
tree | 3b243a7c33dfbbc6414e96a4df6b37ddc47531cd /intern/cycles/render | |
parent | 9d20f170c7c07ac38e86130de591ae98e9c0cf80 (diff) |
Cycles: change volume step size controls, auto adjust based on voxel size
By default it will now set the step size to the voxel size for smoke and
volume objects, and 1/10th the bounding box for procedural volume shaders.
New settings are:
* Scene render/preview step rate: to globally adjust detail and performance
* Material step rate: multiplied with auto detected per-object step size
* World step size: distance to steo for world shader
Differential Revision: https://developer.blender.org/D1777
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/background.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/background.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/integrator.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/integrator.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 71 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 18 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 8 |
12 files changed, 106 insertions, 20 deletions
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index 6553ca735e4..5a61ead2c54 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -43,6 +43,8 @@ NODE_DEFINE(Background) SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false); SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f); + SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f); + SOCKET_NODE(shader, "Shader", &Shader::node_type); return type; @@ -91,6 +93,8 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene else kbackground->volume_shader = SHADER_NONE; + kbackground->volume_step_size = volume_step_size * scene->integrator->volume_step_rate; + /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */ if (bg_shader->graph->nodes.size() <= 1) { kbackground->surface_shader |= SHADER_EXCLUDE_ANY; diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h index fb27430f9a3..c2ca1f75179 100644 --- a/intern/cycles/render/background.h +++ b/intern/cycles/render/background.h @@ -45,6 +45,8 @@ class Background : public Node { bool transparent_glass; float transparent_roughness_threshold; + float volume_step_size; + bool need_update; Background(); diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index ee1aa5988bf..d856f7a300f 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -50,7 +50,7 @@ NODE_DEFINE(Integrator) SOCKET_INT(ao_bounces, "AO Bounces", 0); SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024); - SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f); + SOCKET_FLOAT(volume_step_rate, "Volume Step Rate", 1.0f); SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true); SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true); @@ -143,7 +143,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene } kintegrator->volume_max_steps = volume_max_steps; - kintegrator->volume_step_size = volume_step_size; + kintegrator->volume_step_rate = volume_step_rate; kintegrator->caustics_reflective = caustics_reflective; kintegrator->caustics_refractive = caustics_refractive; diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 9930e907aea..9804caebe6e 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -45,7 +45,7 @@ class Integrator : public Node { int ao_bounces; int volume_max_steps; - float volume_step_size; + float volume_step_rate; bool caustics_reflective; bool caustics_refractive; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 4987b6089d7..c84007823d2 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -17,6 +17,7 @@ #include "render/camera.h" #include "device/device.h" #include "render/hair.h" +#include "render/integrator.h" #include "render/light.h" #include "render/mesh.h" #include "render/curves.h" @@ -65,6 +66,7 @@ struct UpdateObjectTransformState { KernelObject *objects; Transform *object_motion_pass; DecomposedTransform *object_motion; + float *object_volume_step; /* Flags which will be synchronized to Integrator. */ bool have_motion; @@ -266,6 +268,65 @@ uint Object::visibility_for_tracing() const return trace_visibility; } +float Object::compute_volume_step_size() const +{ + if (!geometry->has_volume) { + return FLT_MAX; + } + + /* Compute step rate from shaders. */ + float step_rate = FLT_MAX; + + foreach (Shader *shader, geometry->used_shaders) { + if (shader->has_volume) { + if ((shader->heterogeneous_volume && shader->has_volume_spatial_varying) || + (shader->has_volume_attribute_dependency)) { + step_rate = fminf(shader->volume_step_rate, step_rate); + } + } + } + + if (step_rate == FLT_MAX) { + return FLT_MAX; + } + + /* Compute step size from voxel grids. */ + float step_size = FLT_MAX; + + foreach (Attribute &attr, geometry->attributes.attributes) { + if (attr.element == ATTR_ELEMENT_VOXEL) { + ImageHandle &handle = attr.data_voxel(); + const ImageMetaData &metadata = handle.metadata(); + if (metadata.width == 0 || metadata.height == 0 || metadata.depth == 0) { + continue; + } + + /* Step size is transformed from voxel to world space. */ + Transform voxel_tfm = tfm; + if (metadata.use_transform_3d) { + voxel_tfm = tfm * transform_inverse(metadata.transform_3d); + } + + float3 size = make_float3( + 1.0f / metadata.width, 1.0f / metadata.height, 1.0f / metadata.depth); + float voxel_step_size = min3(fabs(transform_direction(&voxel_tfm, size))); + + if (voxel_step_size > 0.0f) { + step_size = fminf(voxel_step_size, step_size); + } + } + } + + if (step_size == FLT_MAX) { + /* Fall back to 1/10th of bounds for procedural volumes. */ + step_size = 0.1f * average(bounds.size()); + } + + step_size *= step_rate; + + return step_size; +} + int Object::get_device_index() const { return index; @@ -451,6 +512,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s flag |= SD_OBJECT_HOLDOUT_MASK; } state->object_flag[ob->index] = flag; + state->object_volume_step[ob->index] = FLT_MAX; /* Have curves. */ if (geom->type == Geometry::HAIR) { @@ -504,6 +566,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, state.objects = dscene->objects.alloc(scene->objects.size()); state.object_flag = dscene->object_flag.alloc(scene->objects.size()); + state.object_volume_step = dscene->object_volume_step.alloc(scene->objects.size()); state.object_motion = NULL; state.object_motion_pass = NULL; @@ -624,6 +687,7 @@ void ObjectManager::device_update_flags( /* Object info flag. */ uint *object_flag = dscene->object_flag.data(); + float *object_volume_step = dscene->object_volume_step.data(); /* Object volume intersection. */ vector<Object *> volume_objects; @@ -634,6 +698,10 @@ void ObjectManager::device_update_flags( volume_objects.push_back(object); } has_volume_objects = true; + object_volume_step[object->index] = object->compute_volume_step_size(); + } + else { + object_volume_step[object->index] = FLT_MAX; } } @@ -651,6 +719,7 @@ void ObjectManager::device_update_flags( else { object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME | SD_OBJECT_HAS_VOLUME_ATTRIBUTES); } + if (object->is_shadow_catcher) { object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER; } @@ -679,6 +748,7 @@ void ObjectManager::device_update_flags( /* Copy object flag. */ dscene->object_flag.copy_to_device(); + dscene->object_volume_step.copy_to_device(); } void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene) @@ -725,6 +795,7 @@ void ObjectManager::device_free(Device *, DeviceScene *dscene) dscene->object_motion_pass.free(); dscene->object_motion.free(); dscene->object_flag.free(); + dscene->object_volume_step.free(); } void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 7bd3edf769b..2c2870cd0f2 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -97,6 +97,9 @@ class Object : public Node { /* Returns the index that is used in the kernel for this object. */ int get_device_index() const; + /* Compute step size from attributes, shaders, transforms. */ + float compute_volume_step_size() const; + protected: /* Specifies the position of the object in scene->objects and * in the device vectors. Gets set in device_update. */ diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index d17d7270cd5..74eb61e2dff 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -760,16 +760,14 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) else if (current_type == SHADER_TYPE_VOLUME) { if (node->has_spatial_varying()) current_shader->has_volume_spatial_varying = true; + if (node->has_attribute_dependency()) + current_shader->has_volume_attribute_dependency = true; } if (node->has_object_dependency()) { current_shader->has_object_dependency = true; } - if (node->has_attribute_dependency()) { - current_shader->has_attribute_dependency = true; - } - if (node->has_integrator_dependency()) { current_shader->has_integrator_dependency = true; } @@ -1143,8 +1141,8 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_displacement = false; shader->has_surface_spatial_varying = false; shader->has_volume_spatial_varying = false; + shader->has_volume_attribute_dependency = false; shader->has_object_dependency = false; - shader->has_attribute_dependency = false; shader->has_integrator_dependency = false; /* generate surface shader */ diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 76f62fd6690..77c66779c20 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -63,6 +63,7 @@ DeviceScene::DeviceScene(Device *device) object_motion_pass(device, "__object_motion_pass", MEM_GLOBAL), object_motion(device, "__object_motion", MEM_GLOBAL), object_flag(device, "__object_flag", MEM_GLOBAL), + object_volume_step(device, "__object_volume_step", MEM_GLOBAL), camera_motion(device, "__camera_motion", MEM_GLOBAL), attributes_map(device, "__attributes_map", MEM_GLOBAL), attributes_float(device, "__attributes_float", MEM_GLOBAL), diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index d2570138b53..6b10a901d7b 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -91,6 +91,7 @@ class DeviceScene { device_vector<Transform> object_motion_pass; device_vector<DecomposedTransform> object_motion; device_vector<uint> object_flag; + device_vector<float> object_volume_step; /* cameras */ device_vector<DecomposedTransform> camera_motion; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index cc6eb2e5e7f..747fc58f81a 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -178,6 +178,8 @@ NODE_DEFINE(Shader) volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR); + SOCKET_FLOAT(volume_step_rate, "Volume Step Rate", 1.0f); + static NodeEnum displacement_method_enum; displacement_method_enum.insert("bump", DISPLACE_BUMP); displacement_method_enum.insert("true", DISPLACE_TRUE); @@ -203,10 +205,11 @@ Shader::Shader() : Node(node_type) has_bssrdf_bump = false; has_surface_spatial_varying = false; has_volume_spatial_varying = false; + has_volume_attribute_dependency = false; has_object_dependency = false; - has_attribute_dependency = false; has_integrator_dependency = false; has_volume_connected = false; + prev_volume_step_rate = 0.0f; displacement_method = DISPLACE_BUMP; @@ -353,9 +356,10 @@ void Shader::tag_update(Scene *scene) scene->geometry_manager->need_update = true; } - if (has_volume != prev_has_volume) { + if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) { scene->geometry_manager->need_flags_update = true; scene->object_manager->need_flags_update = true; + prev_volume_step_rate = volume_step_rate; } } @@ -533,10 +537,12 @@ void ShaderManager::device_update_common(Device *device, /* in this case we can assume transparent surface */ if (shader->has_volume_connected && !shader->has_surface) flag |= SD_HAS_ONLY_VOLUME; - if (shader->heterogeneous_volume && shader->has_volume_spatial_varying) - flag |= SD_HETEROGENEOUS_VOLUME; - if (shader->has_attribute_dependency) - flag |= SD_NEED_ATTRIBUTES; + if (shader->has_volume) { + if (shader->heterogeneous_volume && shader->has_volume_spatial_varying) + flag |= SD_HETEROGENEOUS_VOLUME; + } + if (shader->has_volume_attribute_dependency) + flag |= SD_NEED_VOLUME_ATTRIBUTES; if (shader->has_bssrdf_bump) flag |= SD_HAS_BSSRDF_BUMP; if (device->info.has_volume_decoupled) { diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 5a5b42de994..1509150228f 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -92,6 +92,8 @@ class Shader : public Node { bool heterogeneous_volume; VolumeSampling volume_sampling_method; int volume_interpolation_method; + float volume_step_rate; + float prev_volume_step_rate; /* synchronization */ bool need_update; @@ -118,8 +120,8 @@ class Shader : public Node { bool has_bssrdf_bump; bool has_surface_spatial_varying; bool has_volume_spatial_varying; + bool has_volume_attribute_dependency; bool has_object_dependency; - bool has_attribute_dependency; bool has_integrator_dependency; /* displacement */ diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 2946614a3b7..c4218f7df1e 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -444,16 +444,14 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done) else if (current_type == SHADER_TYPE_VOLUME) { if (node->has_spatial_varying()) current_shader->has_volume_spatial_varying = true; + if (node->has_attribute_dependency()) + current_shader->has_volume_attribute_dependency = true; } if (node->has_object_dependency()) { current_shader->has_object_dependency = true; } - if (node->has_attribute_dependency()) { - current_shader->has_attribute_dependency = true; - } - if (node->has_integrator_dependency()) { current_shader->has_integrator_dependency = true; } @@ -864,8 +862,8 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum shader->has_displacement = false; shader->has_surface_spatial_varying = false; shader->has_volume_spatial_varying = false; + shader->has_volume_attribute_dependency = false; shader->has_object_dependency = false; - shader->has_attribute_dependency = false; shader->has_integrator_dependency = false; /* generate bump shader */ |