diff options
-rw-r--r-- | intern/cycles/blender/blender_volume.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_object.h | 9 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/mesh_volume.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 52 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_volume.py | 24 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_volume_render.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/volume_render.cc | 15 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_volumes.c | 4 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl | 7 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_volume.c | 3 |
13 files changed, 126 insertions, 20 deletions
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index ee64796b393..6254a1a1b24 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -207,7 +207,7 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float continue; } - mesh->volume_isovalue = b_domain.clipping(); + mesh->volume_clipping = b_domain.clipping(); Attribute *attr = mesh->attributes.add(std); @@ -292,7 +292,11 @@ static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *s BL::Volume b_volume(b_ob.data()); b_volume.grids.load(b_data.ptr.data); - mesh->volume_isovalue = 1e-3f; /* TODO: make user setting. */ + BL::VolumeRender b_render(b_volume.render()); + + mesh->volume_clipping = b_render.clipping(); + mesh->volume_step_size = b_render.step_size(); + mesh->volume_object_space = (b_render.space() == BL::VolumeRender::space_OBJECT); /* Find grid with matching name. */ BL::Volume::grids_iterator b_grid_iter; diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index c6d02ed9702..3aa68e1f84e 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -322,6 +322,15 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object) /* Volume step size */ +ccl_device_inline float object_volume_density(KernelGlobals *kg, int object) +{ + if (object == OBJECT_NONE) { + return 1.0f; + } + + return kernel_tex_fetch(__objects, object).surface_area; +} + ccl_device_inline float object_volume_step_size(KernelGlobals *kg, int object) { if (object == OBJECT_NONE) { diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 035fcdbc8e1..b4f9d2186f4 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -48,7 +48,8 @@ ccl_device_inline bool volume_shader_extinction_sample(KernelGlobals *kg, shader_eval_volume(kg, sd, state, state->volume_stack, PATH_RAY_SHADOW); if (sd->flag & SD_EXTINCTION) { - *extinction = sd->closure_transparent_extinction; + const float density = object_volume_density(kg, sd->object); + *extinction = sd->closure_transparent_extinction * density; return true; } else { @@ -84,6 +85,11 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals *kg, } } + const float density = object_volume_density(kg, sd->object); + coeff->sigma_s *= density; + coeff->sigma_t *= density; + coeff->emission *= density; + return true; } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index e80e87f2980..f855697b889 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -145,7 +145,9 @@ Mesh::Mesh() : Geometry(node_type, Geometry::MESH), subd_attributes(this, ATTR_P num_subd_verts = 0; - volume_isovalue = 0.001f; + volume_clipping = 0.001f; + volume_step_size = 0.0f; + volume_object_space = false; num_ngons = 0; diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 5583e9c0400..d0cf4d557aa 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -133,7 +133,9 @@ class Mesh : public Geometry { array<int> triangle_patch; /* must be < 0 for non subd triangles */ array<float2> vert_patch_uv; - float volume_isovalue; + float volume_clipping; + float volume_step_size; + bool volume_object_space; array<SubdFace> subd_faces; array<int> subd_face_corners; diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp index 6087fba7a98..241be2d7592 100644 --- a/intern/cycles/render/mesh_volume.cpp +++ b/intern/cycles/render/mesh_volume.cpp @@ -450,7 +450,7 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) /* Build bounding mesh around non-empty volume cells. */ VolumeMeshBuilder builder(&volume_params); - const float isovalue = mesh->volume_isovalue; + const float clipping = mesh->volume_clipping; for (int z = 0; z < resolution.z; ++z) { for (int y = 0; y < resolution.y; ++y) { @@ -462,7 +462,7 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) const int channels = voxel_grid.channels; for (int c = 0; c < channels; c++) { - if (voxel_grid.data[voxel_index * channels + c] >= isovalue) { + if (voxel_grid.data[voxel_index * channels + c] >= clipping) { builder.add_node_with_padding(x, y, z); break; } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index c84007823d2..342a641c0be 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -270,14 +270,20 @@ uint Object::visibility_for_tracing() const float Object::compute_volume_step_size() const { - if (!geometry->has_volume) { + if (geometry->type != Geometry::MESH) { + return FLT_MAX; + } + + Mesh *mesh = static_cast<Mesh *>(geometry); + + if (!mesh->has_volume) { return FLT_MAX; } /* Compute step rate from shaders. */ float step_rate = FLT_MAX; - foreach (Shader *shader, geometry->used_shaders) { + foreach (Shader *shader, mesh->used_shaders) { if (shader->has_volume) { if ((shader->heterogeneous_volume && shader->has_volume_spatial_varying) || (shader->has_volume_attribute_dependency)) { @@ -293,7 +299,7 @@ float Object::compute_volume_step_size() const /* Compute step size from voxel grids. */ float step_size = FLT_MAX; - foreach (Attribute &attr, geometry->attributes.attributes) { + foreach (Attribute &attr, mesh->attributes.attributes) { if (attr.element == ATTR_ELEMENT_VOXEL) { ImageHandle &handle = attr.data_voxel(); const ImageMetaData &metadata = handle.metadata(); @@ -301,15 +307,26 @@ float Object::compute_volume_step_size() const 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); - } + /* User specified step size. */ + float voxel_step_size = mesh->volume_step_size; + + if (voxel_step_size == 0.0f) { + /* Auto detect step size. */ + float3 size = make_float3( + 1.0f / metadata.width, 1.0f / metadata.height, 1.0f / metadata.depth); - 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))); + /* 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); + } + voxel_step_size = min3(fabs(transform_direction(&voxel_tfm, size))); + } + else if (mesh->volume_object_space) { + /* User specified step size in object space. */ + float3 size = make_float3(voxel_step_size, voxel_step_size, voxel_step_size); + voxel_step_size = min3(fabs(transform_direction(&tfm, size))); + } if (voxel_step_size > 0.0f) { step_size = fminf(voxel_step_size, step_size); @@ -352,12 +369,23 @@ static float object_surface_area(UpdateObjectTransformState *state, return 0.0f; } + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->has_volume) { + /* Volume density automatically adjust to object scale. */ + if (mesh->volume_object_space) { + const float3 unit = normalize(make_float3(1.0f, 1.0f, 1.0f)); + return 1.0f / len(transform_direction(&tfm, unit)); + } + else { + return 1.0f; + } + } + /* Compute surface area. for uniform scale we can do avoid the many * transform calls and share computation for instances. * * TODO(brecht): Correct for displacement, and move to a better place. */ - Mesh *mesh = static_cast<Mesh *>(geom); float surface_area = 0.0f; float uniform_scale; if (transform_uniform_scale(tfm, uniform_scale)) { diff --git a/release/scripts/startup/bl_ui/properties_data_volume.py b/release/scripts/startup/bl_ui/properties_data_volume.py index bc098e81ffb..b10bb808edd 100644 --- a/release/scripts/startup/bl_ui/properties_data_volume.py +++ b/release/scripts/startup/bl_ui/properties_data_volume.py @@ -108,6 +108,29 @@ class DATA_PT_volume_grids(DataButtonsPanel, Panel): layout.template_list("VOLUME_UL_grids", "grids", volume, "grids", volume.grids, "active_index", rows=3) +class DATA_PT_volume_render(DataButtonsPanel, Panel): + bl_label = "Render" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + scene = context.scene + volume = context.volume + render = volume.render + + col = layout.column(align=True) + col.prop(render, "space") + + if scene.render.engine == 'CYCLES': + col.prop(render, "step_size") + + col = layout.column(align=True) + col.prop(render, "clipping") + + class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel): bl_label = "Viewport Display" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} @@ -140,6 +163,7 @@ classes = ( DATA_PT_volume_grids, DATA_PT_volume_file, DATA_PT_volume_viewport_display, + DATA_PT_volume_render, DATA_PT_custom_props_volume, VOLUME_UL_grids, ) diff --git a/source/blender/blenkernel/BKE_volume_render.h b/source/blender/blenkernel/BKE_volume_render.h index 72360f316a0..53f683f0eaf 100644 --- a/source/blender/blenkernel/BKE_volume_render.h +++ b/source/blender/blenkernel/BKE_volume_render.h @@ -65,6 +65,10 @@ void BKE_volume_grid_wireframe(const struct Volume *volume, BKE_volume_wireframe_cb cb, void *cb_userdata); +/* Render */ + +float BKE_volume_density_scale(const struct Volume *volume, const float matrix[4][4]); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/volume_render.cc b/source/blender/blenkernel/intern/volume_render.cc index d8fbbce3bae..a4833f1ffa4 100644 --- a/source/blender/blenkernel/intern/volume_render.cc +++ b/source/blender/blenkernel/intern/volume_render.cc @@ -356,3 +356,18 @@ void BKE_volume_grid_wireframe(const Volume *volume, cb(cb_userdata, NULL, NULL, 0, 0); #endif } + +/* Render */ + +float BKE_volume_density_scale(const Volume *volume, const float matrix[4][4]) +{ + if (volume->render.space == VOLUME_SPACE_OBJECT) { + float unit[3] = {1.0f, 1.0f, 1.0f}; + normalize_v3(unit); + mul_mat3_m4_v3(matrix, unit); + return 1.0f / len_v3(unit); + } + else { + return 1.0f; + } +} diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 0e82ac237c0..e0008558135 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -451,6 +451,10 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoLoc", (float[3]){0.5f, 0.5f, 0.5f}); DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoSize", (float[3]){0.5f, 0.5f, 0.5f}); + /* Set density scale. */ + const float density_scale = BKE_volume_density_scale(volume, ob->obmat); + DRW_shgroup_uniform_float_copy(grp, "volumeDensityScale", density_scale); + /* Bind volume grid textures. */ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name); diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index f5e92cd7495..312fc07054a 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -8,6 +8,7 @@ uniform vec3 volumeOrcoLoc; uniform vec3 volumeOrcoSize; uniform mat4 volumeObjectToTexture; +uniform float volumeDensityScale = 1.0; #endif flat in int slice; @@ -52,6 +53,12 @@ void main() Closure cl = nodetree_exec(); #endif +#ifdef MESH_SHADER + cl.scatter *= volumeDensityScale; + cl.absorption *= volumeDensityScale; + cl.emission *= volumeDensityScale; +#endif + volumeScattering = vec4(cl.scatter, 1.0); volumeExtinction = vec4(cl.absorption + cl.scatter, 1.0); volumeEmissive = vec4(cl.emission, 1.0); diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index 1eccc99d9e9..b9ea61fd013 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -229,7 +229,8 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata, step_length = len_v3(slice_ct); /* Compute density scale. */ - const float density_scale = volume->display.density; + const float density_scale = volume->display.density * + BKE_volume_density_scale(volume, ob->obmat); /* Set uniforms. */ DRWShadingGroup *grp = DRW_shgroup_create(sh, vedata->psl->volume_ps); |