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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-17 18:27:08 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-18 13:23:05 +0300
commitfd53b72871e045dfebfb9ddbe2b3c491491aa913 (patch)
tree892721f97e6bff16c9d87bc3ffee295d2f4a77bc /source/blender/draw/engines/eevee/eevee_volumes.c
parentb0a1cf2c9ae696b07f7a236bc855a5ab4a493dcb (diff)
Objects: Eevee and workbench rendering of new Volume, Hair, PointCloud
Only the volume drawing part is really finished and exposed to the user. Hair plugs into the existing hair rendering code and is fairly straightforward. The pointcloud drawing is a hack using overlays rather than Eevee and workbench. The most tricky part for volume rendering is the case where each volume grid has a different transform, which requires an additional matrix in the shader and non-trivial logic in Eevee volume drawing. In the common case were all the transforms match we don't use the additional per-grid matrix in the shader. Ref T73201, T68981 Differential Revision: https://developer.blender.org/D6955
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);