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:
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_volumes.c')
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c218
1 files changed, 163 insertions, 55 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 41f8dddf0fb..0e82ac237c0 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -29,11 +29,15 @@
#include "DNA_object_force_types.h"
#include "DNA_fluid_types.h"
+#include "DNA_volume_types.h"
#include "DNA_world_types.h"
-#include "BKE_modifier.h"
-#include "BKE_mesh.h"
#include "BKE_fluid.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_volume.h"
+#include "BKE_volume_render.h"
#include "ED_screen.h"
@@ -59,6 +63,7 @@ static struct {
GPUTexture *depth_src;
GPUTexture *dummy_density;
+ GPUTexture *dummy_color;
GPUTexture *dummy_flame;
GPUTexture *dummy_scatter;
@@ -368,8 +373,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid;
- gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
@@ -390,64 +394,92 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-typedef struct EEVEE_InstanceVolumeMatrix {
- DrawData dd;
- float volume_mat[4][4];
-} EEVEE_InstanceVolumeMatrix;
-
-void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Scene *scene,
- Object *ob)
+static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWShadingGroup *grp)
{
- static const float white[3] = {1.0f, 1.0f, 1.0f};
-
- float *texcoloc = NULL;
- float *texcosize = NULL;
- struct ModifierData *md = NULL;
- Material *ma = BKE_object_material_get(ob, 1);
-
- if (ma == NULL) {
- return;
+ Volume *volume = ob->data;
+ BKE_volume_load(volume, G.main);
+
+ /* Test if we need to use multiple transforms. */
+ DRWVolumeGrid *first_drw_grid = NULL;
+ bool multiple_transforms = true;
+
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
+ VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name);
+ DRWVolumeGrid *drw_grid = (volume_grid) ?
+ DRW_volume_batch_cache_get_grid(volume, volume_grid) :
+ NULL;
+
+ if (drw_grid) {
+ if (first_drw_grid == NULL) {
+ first_drw_grid = drw_grid;
+ }
+ else if (drw_grid &&
+ !equals_m4m4(drw_grid->object_to_texture, first_drw_grid->object_to_texture)) {
+ multiple_transforms = true;
+ break;
+ }
+ }
}
- float size[3];
- mat4_to_size(size, ob->obmat);
- /* Check if any of the axes have 0 length. (see T69070) */
- const float epsilon = 1e-8f;
- if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) {
- return;
+ /* Bail out of no grids to render. */
+ if (first_drw_grid == NULL) {
+ return false;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
- eGPUMaterialStatus status = GPU_material_status(mat);
-
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
+ /* Set transform matrix for the volume as a whole. This one is also used for
+ * clipping so must map the entire bounding box to 0..1. */
+ float bounds_to_object[4][4];
+
+ if (multiple_transforms) {
+ /* For multiple grids with different transform, we first transform from object space
+ * to bounds, then for each individual grid from bounds to texture. */
+ BoundBox *bb = BKE_volume_boundbox_get(ob);
+ float bb_size[3];
+ sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]);
+ size_to_mat4(bounds_to_object, bb_size);
+ copy_v3_v3(bounds_to_object[3], bb->vec[0]);
+
+ invert_m4_m4(first_drw_grid->object_to_bounds, bounds_to_object);
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_bounds);
}
- /* If shader failed to compile or is currently compiling. */
- if (status != GPU_MAT_SUCCESS) {
- return;
+ else {
+ /* All grid transforms are equal, we can transform to texture space immediately. */
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_texture);
}
- DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
-
- BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, &texcosize);
+ /* Don't use orco transform here, only matrix. */
+ 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});
+
+ /* Bind volume grid textures. */
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
+ VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name);
+ DRWVolumeGrid *drw_grid = (volume_grid) ?
+ DRW_volume_batch_cache_get_grid(volume, volume_grid) :
+ NULL;
+
+ DRW_shgroup_uniform_texture(
+ grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_density);
+
+ if (drw_grid && multiple_transforms) {
+ /* Specify per-volume tranform matrix that is applied after the
+ * transform from object to bounds. */
+ mul_m4_m4m4(drw_grid->bounds_to_texture, drw_grid->object_to_texture, bounds_to_object);
+ DRW_shgroup_uniform_mat4(grp, gpu_grid->transform_name, drw_grid->bounds_to_texture);
+ }
+ }
- /* TODO(fclem) remove those "unnecessary" UBOs */
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ return true;
+}
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
+static bool eevee_volume_object_mesh_init(Scene *scene,
+ Object *ob,
+ ListBase *gpu_grids,
+ DRWShadingGroup *grp)
+{
+ static const float white[3] = {1.0f, 1.0f, 1.0f};
+ ModifierData *md = NULL;
- ListBase gpu_grids = GPU_material_volume_grids(mat);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Fluid)) &&
@@ -458,7 +490,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
/* Don't try to show liquid domains here. */
if (!mds->fluid || !(mds->type == FLUID_DOMAIN_TYPE_GAS)) {
- return;
+ return false;
}
/* Don't show smoke before simulation starts, this could be made an option in the future. */
@@ -479,7 +511,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd));
}
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
if (STREQ(gpu_grid->name, "density")) {
DRW_shgroup_uniform_texture_ref(grp,
gpu_grid->sampler_name,
@@ -510,10 +542,85 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &mds->flame_ignition, 1);
}
else {
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
- DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
+ }
+
+ /* Transform for mesh volumes. */
+ static const float unit_mat[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}};
+ float *texco_loc, *texco_size;
+ BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texco_loc, &texco_size);
+
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", unit_mat);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texco_loc, 1);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texco_size, 1);
+
+ return true;
+}
+
+void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ Scene *scene,
+ Object *ob)
+{
+ Material *ma = BKE_object_material_get(ob, 1);
+
+ if (ma == NULL) {
+ if (ob->type == OB_VOLUME) {
+ ma = BKE_material_default_volume();
+ }
+ else {
+ return;
+ }
+ }
+
+ float size[3];
+ mat4_to_size(size, ob->obmat);
+ /* Check if any of the axes have 0 length. (see T69070) */
+ const float epsilon = 1e-8f;
+ if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) {
+ return;
+ }
+
+ struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ eGPUMaterialStatus status = GPU_material_status(mat);
+
+ if (status == GPU_MAT_QUEUED) {
+ vedata->stl->g_data->queued_shaders_count++;
+ }
+ /* If shader failed to compile or is currently compiling. */
+ if (status != GPU_MAT_SUCCESS) {
+ return;
+ }
+
+ DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
+
+ /* TODO(fclem) remove those "unnecessary" UBOs */
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(
+ grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ ListBase gpu_grids = GPU_material_volume_grids(mat);
+
+ if (ob->type == OB_VOLUME) {
+ if (!eevee_volume_object_grids_init(ob, &gpu_grids, grp)) {
+ return;
+ }
+ }
+ else {
+ if (!eevee_volume_object_mesh_init(scene, ob, &gpu_grids, grp)) {
+ return;
+ }
}
/* TODO Reduce to number of slices intersecting. */
@@ -757,6 +864,7 @@ void EEVEE_volumes_free(void)
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);