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')
-rw-r--r--source/blender/draw/CMakeLists.txt6
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c20
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h4
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c218
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl3
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c25
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c16
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h7
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c22
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c15
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl16
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl7
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c46
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h6
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c11
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c135
-rw-r--r--source/blender/draw/intern/draw_cache.c75
-rw-r--r--source/blender/draw/intern/draw_cache.h35
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h33
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c16
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c2
-rw-r--r--source/blender/draw/intern/draw_common.c10
-rw-r--r--source/blender/draw/intern/draw_hair.c65
-rw-r--r--source/blender/draw/intern/draw_hair_private.h7
-rw-r--r--source/blender/draw/intern/draw_manager.c12
27 files changed, 698 insertions, 129 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 81f2214b402..46263f694cb 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -53,10 +53,13 @@ set(SRC
intern/draw_cache_impl_curve.c
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_gpencil.c
+ intern/draw_cache_impl_hair.c
intern/draw_cache_impl_lattice.c
intern/draw_cache_impl_mesh.c
intern/draw_cache_impl_metaball.c
intern/draw_cache_impl_particles.c
+ intern/draw_cache_impl_pointcloud.c
+ intern/draw_cache_impl_volume.c
intern/draw_color_management.c
intern/draw_common.c
intern/draw_debug.c
@@ -139,6 +142,7 @@ set(SRC
engines/overlay/overlay_outline.c
engines/overlay/overlay_paint.c
engines/overlay/overlay_particle.c
+ engines/overlay/overlay_pointcloud.c
engines/overlay/overlay_sculpt.c
engines/overlay/overlay_shader.c
engines/overlay/overlay_wireframe.c
@@ -377,6 +381,8 @@ data_to_c_simple(engines/overlay/shaders/paint_weight_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/particle_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/particle_frag.glsl SRC)
+data_to_c_simple(engines/overlay/shaders/pointcloud_vert.glsl SRC)
+data_to_c_simple(engines/overlay/shaders/pointcloud_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a886fa26589..70933e21719 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -127,6 +127,12 @@ void EEVEE_cache_populate(void *vedata, Object *ob)
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow);
}
+ else if (ob->type == OB_HAIR) {
+ EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
+ }
+ else if (ob->type == OB_VOLUME) {
+ EEVEE_volumes_cache_object_add(sldata, vedata, draw_ctx->scene, ob);
+ }
else if (!USE_SCENE_LIGHT(draw_ctx->v3d)) {
/* do not add any scene light sources to the cache */
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 230a0725493..bb64fe32bc3 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -32,9 +32,10 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "DNA_world_types.h"
+#include "DNA_hair_types.h"
#include "DNA_modifier_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
#include "GPU_material.h"
@@ -1021,7 +1022,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
EEVEE_PassList *psl = vedata->psl;
- BLI_assert(!is_hair || (ob && psys && md));
+ BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
@@ -1715,7 +1716,12 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot)
{
Material *ma = BKE_object_material_get(ob, slot + 1);
if (ma == NULL) {
- ma = BKE_material_default_empty();
+ if (ob->type == OB_VOLUME) {
+ ma = BKE_material_default_volume();
+ }
+ else {
+ ma = BKE_material_default_empty();
+ }
}
return ma;
}
@@ -2064,6 +2070,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
}
}
+void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Object *ob,
+ bool *cast_shadow)
+{
+ eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, HAIR_MATERIAL_NR, cast_shadow);
+}
+
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 52fb8b3cced..e2470b4fa76 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -902,6 +902,10 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow);
+void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Object *ob,
+ bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index eedc64f32e6..c8357b56b18 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -177,7 +177,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
void EEVEE_render_cache(void *vedata,
struct Object *ob,
struct RenderEngine *engine,
- struct Depsgraph *UNUSED(depsgraph))
+ struct Depsgraph *depsgraph)
{
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -211,6 +211,13 @@ void EEVEE_render_cache(void *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow);
}
+ else if (ob->type == OB_HAIR) {
+ EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
+ }
+ else if (ob->type == OB_VOLUME) {
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
+ }
else if (ob->type == OB_LIGHTPROBE) {
EEVEE_lightprobes_cache_add(sldata, vedata, ob);
}
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);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 2b1ae60654e..f5e92cd7495 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -7,6 +7,7 @@
#ifdef MESH_SHADER
uniform vec3 volumeOrcoLoc;
uniform vec3 volumeOrcoSize;
+uniform mat4 volumeObjectToTexture;
#endif
flat in int slice;
@@ -35,8 +36,10 @@ void main()
worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
volumeObjectLocalCoord = point_world_to_object(worldPosition);
+ /* TODO: redundant transform */
volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) /
(volumeOrcoSize * 2.0);
+ volumeObjectLocalCoord = (volumeObjectToTexture * vec4(volumeObjectLocalCoord, 1.0)).xyz;
if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) ||
any(greaterThan(volumeObjectLocalCoord, vec3(1.0))))
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index 740ca42800e..9b900a53d8d 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -161,6 +161,7 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_motion_path_cache_init(vedata);
OVERLAY_outline_cache_init(vedata);
OVERLAY_particle_cache_init(vedata);
+ OVERLAY_pointcloud_cache_init(vedata);
OVERLAY_wireframe_cache_init(vedata);
}
@@ -205,6 +206,11 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj
return pd->ctx_mode == CTX_MODE_EDIT_METABALL;
case OB_FONT:
return pd->ctx_mode == CTX_MODE_EDIT_TEXT;
+ case OB_HAIR:
+ case OB_POINTCLOUD:
+ case OB_VOLUME:
+ /* No edit mode yet. */
+ return false;
}
}
return false;
@@ -223,8 +229,16 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
- const bool has_surface = ELEM(
- ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT, OB_GPENCIL);
+ const bool has_surface = ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_SURF,
+ OB_MBALL,
+ OB_FONT,
+ OB_GPENCIL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME);
const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE));
const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
@@ -361,6 +375,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
OVERLAY_particle_cache_populate(vedata, ob);
}
+ /* TODO: these should not be overlays, just here for testing since it's
+ * easier to implement than integrating it into eevee/workbench. */
+ if (ob->type == OB_POINTCLOUD) {
+ OVERLAY_pointcloud_cache_populate(vedata, ob);
+ }
+
/* Relationship, object center, bounbox ... */
if (!pd->hide_overlays) {
OVERLAY_extra_cache_populate(vedata, ob);
@@ -434,6 +454,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_armature_draw(vedata);
OVERLAY_particle_draw(vedata);
OVERLAY_metaball_draw(vedata);
+ OVERLAY_pointcloud_draw(vedata);
OVERLAY_gpencil_draw(vedata);
OVERLAY_extra_draw(vedata);
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 53550fb115e..4c525acd5be 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -475,13 +475,25 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons
texcosize = mb->size;
break;
}
+ case ID_HA:
+ case ID_PT:
+ case ID_VO: {
+ /* No user defined texture space support. */
+ break;
+ }
default:
BLI_assert(0);
}
float mat[4][4];
- size_to_mat4(mat, texcosize);
- copy_v3_v3(mat[3], texcoloc);
+
+ if (texcoloc != NULL && texcosize != NULL) {
+ size_to_mat4(mat, texcosize);
+ copy_v3_v3(mat[3], texcoloc);
+ }
+ else {
+ unit_m4(mat);
+ }
mul_m4_m4m4(mat, ob->obmat, mat);
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 167a8e940df..de35d4f760e 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -95,6 +95,7 @@ typedef struct OVERLAY_PassList {
DRWPass *paint_color_ps;
DRWPass *paint_overlay_ps;
DRWPass *particle_ps;
+ DRWPass *pointcloud_ps;
DRWPass *sculpt_mask_ps;
DRWPass *wireframe_ps;
DRWPass *wireframe_xray_ps;
@@ -251,6 +252,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *paint_face_grp;
DRWShadingGroup *particle_dots_grp;
DRWShadingGroup *particle_shapes_grp;
+ DRWShadingGroup *pointcloud_dots_grp;
DRWShadingGroup *sculpt_mask_grp;
DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */
DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */
@@ -532,6 +534,10 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata);
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_particle_draw(OVERLAY_Data *vedata);
+void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata);
+
void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata);
void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_sculpt_draw(OVERLAY_Data *vedata);
@@ -597,6 +603,7 @@ GPUShader *OVERLAY_shader_paint_weight(void);
GPUShader *OVERLAY_shader_paint_wire(void);
GPUShader *OVERLAY_shader_particle_dot(void);
GPUShader *OVERLAY_shader_particle_shape(void);
+GPUShader *OVERLAY_shader_pointcloud_dot(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
GPUShader *OVERLAY_shader_volume_velocity(bool use_needle);
GPUShader *OVERLAY_shader_wireframe(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index d5509c7f56b..0b2f98294ec 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -102,6 +102,8 @@ extern char datatoc_paint_weight_vert_glsl[];
extern char datatoc_paint_wire_vert_glsl[];
extern char datatoc_particle_vert_glsl[];
extern char datatoc_particle_frag_glsl[];
+extern char datatoc_pointcloud_vert_glsl[];
+extern char datatoc_pointcloud_frag_glsl[];
extern char datatoc_sculpt_mask_vert_glsl[];
extern char datatoc_volume_velocity_vert_glsl[];
extern char datatoc_wireframe_vert_glsl[];
@@ -184,6 +186,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *paint_wire;
GPUShader *particle_dot;
GPUShader *particle_shape;
+ GPUShader *pointcloud_dot;
GPUShader *sculpt_mask;
GPUShader *uniform_color;
GPUShader *volume_velocity_needle_sh;
@@ -1272,6 +1275,25 @@ GPUShader *OVERLAY_shader_particle_shape(void)
return sh_data->particle_shape;
}
+GPUShader *OVERLAY_shader_pointcloud_dot(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->pointcloud_dot) {
+ sh_data->pointcloud_dot = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_pointcloud_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_pointcloud_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define USE_DOTS\n", NULL},
+ });
+ }
+ return sh_data->pointcloud_dot;
+}
+
GPUShader *OVERLAY_shader_sculpt_mask(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index 6b0e5e0b72e..cdf8005b827 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -22,6 +22,7 @@
#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_volume_types.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
@@ -163,6 +164,20 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
}
}
+ if (use_wire && ob->type == OB_VOLUME) {
+ /* Volume object as points exception. */
+ Volume *volume = ob->data;
+ if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) {
+ float *color;
+ OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
+ DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
+
+ struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob);
+ OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
+ return;
+ }
+ }
+
const bool is_edit_mode = DRW_object_is_in_edit_mode(ob);
bool has_edit_mesh_cage = false;
if (is_mesh && is_edit_mode) {
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index e957f8bbe9c..0c2b7850f94 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -11,6 +11,7 @@ uniform sampler3D shadowTexture;
uniform sampler3D flameTexture;
uniform sampler1D flameColorTexture;
uniform sampler1D transferTexture;
+uniform mat4 volumeObjectToTexture;
uniform int samplesLen = 256;
uniform float noiseOfs = 0.0;
@@ -110,20 +111,24 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
scattering = tval.rgb * 1500.0;
extinction = max(1e-4, tval.a * 50.0);
#else
+# ifdef VOLUME_SMOKE
float flame = sample_volume_texture(flameTexture, co).r;
vec4 emission = texture(flameColorTexture, flame);
+# endif
+ vec3 density = sample_volume_texture(densityTexture, co).rgb;
float shadows = sample_volume_texture(shadowTexture, co).r;
- vec4 density = sample_volume_texture(densityTexture, co); /* rgb: color, a: density */
- scattering = density.rgb * densityScale;
+ scattering = density * densityScale;
extinction = max(1e-4, dot(scattering, vec3(0.33333)));
scattering *= activeColor;
/* Scale shadows in log space and clamp them to avoid completely black shadows. */
scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI;
+# ifdef VOLUME_SMOKE
/* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */
scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0;
+# endif
#endif
}
@@ -201,9 +206,16 @@ void main()
vec3 ls_ray_ori = point_view_to_object(vs_ray_ori);
vec3 ls_ray_end = point_view_to_object(vs_ray_end);
+# ifdef VOLUME_SMOKE
ls_ray_dir = (OrcoTexCoFactors[0].xyz + ls_ray_dir * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
ls_ray_ori = (OrcoTexCoFactors[0].xyz + ls_ray_ori * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
ls_ray_end = (OrcoTexCoFactors[0].xyz + ls_ray_end * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
+# else
+ ls_ray_dir = (volumeObjectToTexture * vec4(ls_ray_dir, 1.0)).xyz * 2.0f - 1.0;
+ ls_ray_ori = (volumeObjectToTexture * vec4(ls_ray_ori, 1.0)).xyz * 2.0f - 1.0;
+ ls_ray_end = (volumeObjectToTexture * vec4(ls_ray_end, 1.0)).xyz * 2.0f - 1.0;
+# endif
+
ls_ray_dir -= ls_ray_ori;
/* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
index 1a32a202290..7327a92e04f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
@@ -5,6 +5,8 @@
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+uniform mat4 volumeTextureToObject;
+
in vec3 pos;
RESOURCE_ID_VARYING
@@ -31,7 +33,12 @@ void main()
#else
vec3 final_pos = pos;
#endif
+
+#ifdef VOLUME_SMOKE
final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0].xyz) / OrcoTexCoFactors[1].xyz;
+#else
+ final_pos = (volumeTextureToObject * vec4(final_pos * 0.5 + 0.5, 1.0)).xyz;
+#endif
gl_Position = point_object_to_ndc(final_pos);
PASS_RESOURCE_ID
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 742489c7311..e9525af5682 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -33,8 +33,9 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "DNA_image_types.h"
#include "DNA_fluid_types.h"
+#include "DNA_hair_types.h"
+#include "DNA_image_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -192,12 +193,12 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd,
static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
Object *ob,
+ ParticleSystem *psys,
ModifierData *md,
eV3DShadingColorType color_type,
- bool use_texpaint_mode)
+ bool use_texpaint_mode,
+ const int matnr)
{
- ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
- ParticleSettings *part = psys->part;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
@@ -206,8 +207,8 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
int interp = (imapaint && imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
SHD_INTERP_CLOSEST;
DRWShadingGroup *grp = (use_texpaint_mode) ?
- workbench_image_hair_setup(wpd, ob, part->omat, ima, NULL, interp) :
- workbench_material_hair_setup(wpd, ob, part->omat, color_type);
+ workbench_image_hair_setup(wpd, ob, matnr, ima, NULL, interp) :
+ workbench_material_hair_setup(wpd, ob, matnr, color_type);
DRW_shgroup_hair_create_sub(ob, psys, md, grp);
}
@@ -244,14 +245,20 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
color_type = V3D_SHADING_OBJECT_COLOR;
}
- *r_sculpt_pbvh = is_sculpt_pbvh;
- *r_texpaint_mode = false;
+ if (r_sculpt_pbvh) {
+ *r_sculpt_pbvh = is_sculpt_pbvh;
+ }
+ if (r_texpaint_mode) {
+ *r_texpaint_mode = false;
+ }
if (!is_sculpt_pbvh && !is_render) {
/* Force texture or vertex mode if object is in paint mode. */
if (is_texpaint_mode && me && me->mloopuv) {
color_type = V3D_SHADING_TEXTURE_COLOR;
- *r_texpaint_mode = true;
+ if (r_texpaint_mode) {
+ *r_texpaint_mode = true;
+ }
}
else if (is_vertpaint_mode && me && me->mloopcol) {
color_type = V3D_SHADING_VERTEX_COLOR;
@@ -286,8 +293,8 @@ void workbench_cache_populate(void *ved, Object *ob)
}
if (ob->type == OB_MESH && ob->modifiers.first != NULL) {
- bool use_sculpt_pbvh, use_texpaint_mode;
- int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, NULL);
+ bool use_texpaint_mode;
+ int color_type = workbench_color_type_get(wpd, ob, NULL, &use_texpaint_mode, NULL);
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type != eModifierType_ParticleSystem) {
@@ -301,7 +308,8 @@ void workbench_cache_populate(void *ved, Object *ob)
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
- workbench_cache_hair_populate(wpd, ob, md, color_type, use_texpaint_mode);
+ workbench_cache_hair_populate(
+ wpd, ob, psys, md, color_type, use_texpaint_mode, part->omat);
}
}
}
@@ -311,7 +319,7 @@ void workbench_cache_populate(void *ved, Object *ob)
if (md && modifier_isEnabled(wpd->scene, md, eModifierMode_Realtime)) {
FluidModifierData *fmd = (FluidModifierData *)md;
if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
- workbench_volume_cache_populate(vedata, wpd->scene, ob, md);
+ workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR);
return; /* Do not draw solid in this case. */
}
}
@@ -325,7 +333,7 @@ void workbench_cache_populate(void *ved, Object *ob)
return;
}
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_POINTCLOUD)) {
bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false;
eV3DShadingColorType color_type = workbench_color_type_get(
wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow);
@@ -344,6 +352,16 @@ void workbench_cache_populate(void *ved, Object *ob)
workbench_shadow_cache_populate(vedata, ob, has_transp_mat);
}
}
+ else if (ob->type == OB_HAIR) {
+ int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
+ workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, HAIR_MATERIAL_NR);
+ }
+ else if (ob->type == OB_VOLUME) {
+ if (wpd->shading.type != OB_WIRE) {
+ int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
+ workbench_volume_cache_populate(vedata, wpd->scene, ob, NULL, color_type);
+ }
+ }
}
void workbench_cache_finish(void *ved)
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index a68b66e0f85..49becf93f48 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -101,6 +101,7 @@ typedef struct WORKBENCH_TextureList {
struct GPUTexture *smaa_area_tx;
struct GPUTexture *dummy_image_tx;
struct GPUTexture *dummy_volume_tx;
+ struct GPUTexture *dummy_shadow_tx;
struct GPUTexture *dummy_coba_tx;
} WORKBENCH_TextureList;
@@ -405,7 +406,7 @@ GPUShader *workbench_shader_outline_get(void);
GPUShader *workbench_shader_antialiasing_accumulation_get(void);
GPUShader *workbench_shader_antialiasing_get(int stage);
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic);
+GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke);
void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **downsample_sh,
@@ -479,7 +480,8 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata);
void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
struct Scene *UNUSED(scene),
struct Object *ob,
- struct ModifierData *md);
+ struct ModifierData *md,
+ eV3DShadingColorType color_type);
void workbench_volume_draw_pass(WORKBENCH_Data *vedata);
void workbench_volume_draw_finish(WORKBENCH_Data *vedata);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 14a980fe628..2e796056029 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -106,7 +106,7 @@ static struct {
struct GPUShader *aa_accum_sh;
struct GPUShader *smaa_sh[3];
- struct GPUShader *volume_sh[2][2][2];
+ struct GPUShader *volume_sh[2][2][2][2];
struct DRWShaderLibrary *lib;
} e_data = {{{{NULL}}}};
@@ -448,9 +448,9 @@ GPUShader *workbench_shader_antialiasing_get(int stage)
return e_data.smaa_sh[stage];
}
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic)
+GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke)
{
- GPUShader **shader = &e_data.volume_sh[slice][coba][cubic];
+ GPUShader **shader = &e_data.volume_sh[slice][coba][cubic][smoke];
if (*shader == NULL) {
DynStr *ds = BLI_dynstr_new();
@@ -464,6 +464,9 @@ GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic)
if (cubic) {
BLI_dynstr_append(ds, "#define USE_TRICUBIC\n");
}
+ if (smoke) {
+ BLI_dynstr_append(ds, "#define VOLUME_SMOKE\n");
+ }
char *defines = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -513,7 +516,7 @@ void workbench_shader_free(void)
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.volume_sh) / sizeof(void *); j++) {
- struct GPUShader **sh_array = &e_data.volume_sh[0][0][0];
+ struct GPUShader **sh_array = &e_data.volume_sh[0][0][0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index a3072b834bd..1eccc99d9e9 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -22,16 +22,20 @@
#include "workbench_private.h"
-#include "BKE_object.h"
-#include "BKE_fluid.h"
+#include "DNA_fluid_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_force_types.h"
+#include "DNA_volume_types.h"
#include "BLI_rand.h"
#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_force_types.h"
-#include "DNA_fluid_types.h"
+#include "BKE_fluid.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_volume.h"
+#include "BKE_volume_render.h"
#include "GPU_draw.h"
@@ -40,9 +44,11 @@ void workbench_volume_engine_init(WORKBENCH_Data *vedata)
WORKBENCH_TextureList *txl = vedata->txl;
if (txl->dummy_volume_tx == NULL) {
- float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, pixel, NULL);
- txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, pixel, NULL);
+ float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, zero, NULL);
+ txl->dummy_shadow_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, one, NULL);
+ txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, zero, NULL);
}
}
@@ -54,10 +60,9 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata)
vedata->stl->wpd->volumes_do = false;
}
-void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
- Scene *UNUSED(scene),
- Object *ob,
- ModifierData *md)
+static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
+ Object *ob,
+ ModifierData *md)
{
FluidModifierData *mmd = (FluidModifierData *)md;
FluidDomainSettings *mds = mmd->domain;
@@ -90,8 +95,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
const bool use_slice = (mds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
mds->axis_slice_method == AXIS_SLICE_SINGLE);
const bool cubic_interp = (mds->interp_method == VOLUME_INTERP_CUBIC);
-
- GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp);
+ GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp, true);
if (use_slice) {
float invviewmat[4][4];
@@ -162,6 +166,107 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(mmd));
}
+static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd,
+ Object *ob,
+ eV3DShadingColorType color_type,
+ float color[3])
+{
+ Material *ma = BKE_object_material_get(ob, VOLUME_MATERIAL_NR);
+ WORKBENCH_UBO_Material ubo_data;
+ workbench_material_ubo_data(wpd, ob, ma, &ubo_data, color_type);
+ copy_v3_v3(color, ubo_data.base_color);
+}
+
+static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
+ Object *ob,
+ eV3DShadingColorType color_type)
+{
+ /* Create 3D textures. */
+ Volume *volume = ob->data;
+ BKE_volume_load(volume, G.main);
+ VolumeGrid *volume_grid = BKE_volume_grid_active_get(volume);
+ if (volume_grid == NULL) {
+ return;
+ }
+ DRWVolumeGrid *grid = DRW_volume_batch_cache_get_grid(volume, volume_grid);
+ if (grid == NULL) {
+ return;
+ }
+
+ WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
+ WORKBENCH_TextureList *txl = vedata->txl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ wpd->volumes_do = true;
+
+ /* Create shader. */
+ GPUShader *sh = workbench_shader_volume_get(false, false, false, false);
+
+ /* Compute color. */
+ float color[3];
+ workbench_volume_material_color(wpd, ob, color_type, color);
+
+ /* Combined texture to object, and object to world transform. */
+ float texture_to_world[4][4];
+ mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object);
+
+ /* Compute world space dimensions for step size. */
+ float world_size[3];
+ mat4_to_size(world_size, texture_to_world);
+ abs_v3(world_size);
+
+ /* Compute step parameters. */
+ double noise_ofs;
+ BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
+ float step_length, max_slice;
+ int resolution[3];
+ GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
+ float slice_ct[3] = {resolution[0], resolution[1], resolution[2]};
+ mul_v3_fl(slice_ct, max_ff(0.001f, 5.0f));
+ max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]);
+ invert_v3(slice_ct);
+ mul_v3_v3(slice_ct, world_size);
+ step_length = len_v3(slice_ct);
+
+ /* Compute density scale. */
+ const float density_scale = volume->display.density;
+
+ /* Set uniforms. */
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
+ DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
+ DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
+
+ DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture);
+ /* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
+ DRW_shgroup_uniform_texture(grp, "shadowTexture", txl->dummy_shadow_tx);
+ DRW_shgroup_uniform_vec3_copy(grp, "activeColor", color);
+
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_float_copy(grp, "densityScale", density_scale);
+
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", grid->object_to_texture);
+ DRW_shgroup_uniform_mat4(grp, "volumeTextureToObject", grid->texture_to_object);
+
+ DRW_shgroup_call(grp, DRW_cache_cube_get(), ob);
+}
+
+void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
+ Scene *UNUSED(scene),
+ Object *ob,
+ ModifierData *md,
+ eV3DShadingColorType color_type)
+{
+ if (md == NULL) {
+ workbench_volume_object_cache_populate(vedata, ob, color_type);
+ }
+ else {
+ workbench_volume_modifier_cache_populate(vedata, ob, md);
+ }
+}
+
void workbench_volume_draw_pass(WORKBENCH_Data *vedata)
{
WORKBENCH_PassList *psl = vedata->psl;
@@ -189,4 +294,4 @@ void workbench_volume_draw_finish(WORKBENCH_Data *vedata)
GPU_free_smoke(mmd);
}
BLI_freelistN(&wpd->smoke_domains);
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index d0cea5b8c5c..1f76b5ac431 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -19,13 +19,16 @@
*/
#include "DNA_scene_types.h"
+#include "DNA_hair_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_curve_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_pointcloud_types.h"
+#include "DNA_volume_types.h"
#include "UI_resources.h"
@@ -799,6 +802,12 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
return DRW_cache_text_edge_detection_get(ob, r_is_manifold);
case OB_MBALL:
return DRW_cache_mball_edge_detection_get(ob, r_is_manifold);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -817,6 +826,12 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
return DRW_cache_text_face_wireframe_get(ob);
case OB_MBALL:
return DRW_cache_mball_face_wireframe_get(ob);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return DRW_cache_volume_face_wireframe_get(ob);
case OB_GPENCIL: {
return DRW_cache_gpencil_face_wireframe_get(ob);
}
@@ -837,7 +852,13 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
case OB_FONT:
return DRW_cache_text_loose_edges_get(ob);
case OB_MBALL:
- /* Cannot have any loose edge */
+ return NULL;
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -856,6 +877,12 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
return DRW_cache_text_surface_get(ob);
case OB_MBALL:
return DRW_cache_mball_surface_get(ob);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -875,6 +902,12 @@ int DRW_cache_object_material_count_get(struct Object *ob)
return DRW_curve_material_count_get(ob->data);
case OB_MBALL:
return DRW_metaball_material_count_get(ob->data);
+ case OB_HAIR:
+ return DRW_hair_material_count_get(ob->data);
+ case OB_POINTCLOUD:
+ return DRW_pointcloud_material_count_get(ob->data);
+ case OB_VOLUME:
+ return DRW_volume_material_count_get(ob->data);
default:
BLI_assert(0);
return 0;
@@ -896,6 +929,12 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_MBALL:
return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -3214,6 +3253,27 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name PointCloud
+ * \{ */
+
+GPUBatch *DRW_cache_pointcloud_get_dots(Object *object)
+{
+ return DRW_pointcloud_batch_cache_get_dots(object);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Volume
+ * \{ */
+
+GPUBatch *DRW_cache_volume_face_wireframe_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_VOLUME);
+ return DRW_volume_batch_cache_get_wireframes_face(ob->data);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Particles
* \{ */
@@ -3444,6 +3504,15 @@ void drw_batch_cache_validate(Object *ob)
case OB_LATTICE:
DRW_lattice_batch_cache_validate((Lattice *)ob->data);
break;
+ case OB_HAIR:
+ DRW_hair_batch_cache_validate((Hair *)ob->data);
+ break;
+ case OB_POINTCLOUD:
+ DRW_pointcloud_batch_cache_validate((PointCloud *)ob->data);
+ break;
+ case OB_VOLUME:
+ DRW_volume_batch_cache_validate((Volume *)ob->data);
+ break;
default:
break;
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 8ac0d7ada21..77c7b6b9307 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -29,6 +29,8 @@ struct ModifierData;
struct Object;
struct PTCacheEdit;
struct ParticleSystem;
+struct Volume;
+struct VolumeGrid;
struct bGPDstroke;
void DRW_shape_cache_free(void);
@@ -200,6 +202,39 @@ struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob,
struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+/* Hair */
+struct GPUBatch *DRW_cache_hair_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_hair_surface_shaded_get(struct Object *ob,
+ struct GPUMaterial **gpumat_array,
+ uint gpumat_array_len);
+struct GPUBatch *DRW_cache_hair_face_wireframe_get(struct Object *ob);
+struct GPUBatch *DRW_cache_hair_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+
+/* PointCloud */
+struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj);
+
+/* Volume */
+typedef struct DRWVolumeGrid {
+ struct DRWVolumeGrid *next, *prev;
+
+ /* Grid name. */
+ char *name;
+
+ /* 3D texture. */
+ struct GPUTexture *texture;
+
+ /* Transform between 0..1 texture space and object space. */
+ float texture_to_object[4][4];
+ float object_to_texture[4][4];
+
+ /* Transfrom from bounds to texture space. */
+ float object_to_bounds[4][4];
+ float bounds_to_texture[4][4];
+} DRWVolumeGrid;
+
+DRWVolumeGrid *DRW_volume_batch_cache_get_grid(struct Volume *volume, struct VolumeGrid *grid);
+struct GPUBatch *DRW_cache_volume_face_wireframe_get(struct Object *ob);
+
/* GPencil */
struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 755f794d201..b3450bf4715 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -32,11 +32,14 @@ struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
+struct bGPdata;
struct Curve;
+struct Hair;
struct Lattice;
struct Mesh;
struct MetaBall;
-struct bGPdata;
+struct PointCloud;
+struct Volume;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode);
@@ -61,11 +64,26 @@ void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
void DRW_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
void DRW_gpencil_batch_cache_free(struct bGPdata *gpd);
+void DRW_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
+void DRW_hair_batch_cache_validate(struct Hair *hair);
+void DRW_hair_batch_cache_free(struct Hair *hair);
+
+void DRW_pointcloud_batch_cache_dirty_tag(struct PointCloud *pointcloud, int mode);
+void DRW_pointcloud_batch_cache_validate(struct PointCloud *pointcloud);
+void DRW_pointcloud_batch_cache_free(struct PointCloud *pointcloud);
+
+void DRW_volume_batch_cache_dirty_tag(struct Volume *volume, int mode);
+void DRW_volume_batch_cache_validate(struct Volume *volume);
+void DRW_volume_batch_cache_free(struct Volume *volume);
+
/* Garbage collection */
void DRW_batch_cache_free_old(struct Object *ob, int ctime);
void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime);
+/* Generic */
+void DRW_vertbuf_create_wiredata(struct GPUVertBuf *vbo, const int vert_len);
+
/* Curve */
void DRW_curve_batch_cache_create_requested(struct Object *ob);
@@ -118,6 +136,19 @@ struct GPUBatch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt,
struct GPUBatch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt);
+/* Hair */
+int DRW_hair_material_count_get(struct Hair *hair);
+
+/* PointCloud */
+int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud);
+
+struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob);
+
+/* Volume */
+int DRW_volume_material_count_get(struct Volume *volume);
+
+struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume);
+
/* Mesh */
void DRW_mesh_batch_cache_create_requested(struct Object *ob,
struct Mesh *me,
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 50979d72189..bc4eb37c3b4 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -214,7 +214,7 @@ void DRW_displist_vertbuf_create_pos_and_nor(ListBase *lb, GPUVertBuf *vbo)
}
}
-void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
+void DRW_vertbuf_create_wiredata(GPUVertBuf *vbo, const int vert_len)
{
static GPUVertFormat format = {0};
static struct {
@@ -232,23 +232,27 @@ void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
}
}
- int vbo_len_used = curve_render_surface_vert_len_get(lb);
-
GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, vbo_len_used);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
if (vbo->format.stride == 1) {
- memset(vbo->data, 0xFF, (size_t)vbo_len_used);
+ memset(vbo->data, 0xFF, (size_t)vert_len);
}
else {
GPUVertBufRaw wd_step;
GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
- for (int i = 0; i < vbo_len_used; i++) {
+ for (int i = 0; i < vert_len; i++) {
*((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f;
}
}
}
+void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
+{
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+ DRW_vertbuf_create_wiredata(vbo, vert_len);
+}
+
void DRW_displist_indexbuf_create_triangles_in_order(ListBase *lb, GPUIndexBuf *ibo)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index 795e7be63b1..c4433cea0df 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -179,7 +179,7 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
}
-static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
+void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
/* TODO more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index b1ad1455d8c..87cd1cd8546 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -437,7 +437,15 @@ bool DRW_object_is_flat(Object *ob, int *r_axis)
{
float dim[3];
- if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
+ if (!ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_SURF,
+ OB_FONT,
+ OB_MBALL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME)) {
/* Non-meshes object cannot be considered as flat. */
return false;
}
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index c88071dc6d6..c89f5f5bba6 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -142,9 +142,16 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
ParticleHairCache *hair_cache;
- ParticleSettings *part = psys->part;
- bool need_ft_update = particles_ensure_procedural_data(
- object, psys, md, &hair_cache, subdiv, thickness_res);
+ bool need_ft_update;
+ if (psys) {
+ /* Old particle hair. */
+ need_ft_update = particles_ensure_procedural_data(
+ object, psys, md, &hair_cache, subdiv, thickness_res);
+ }
+ else {
+ /* New hair object. */
+ need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
+ }
DRWShadingGroup *shgrp;
if (shgrp_parent) {
@@ -185,34 +192,58 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
}
- if ((dupli_parent != NULL) && (dupli_object != NULL)) {
- if (dupli_object->type & OB_DUPLICOLLECTION) {
- copy_m4_m4(dupli_mat, dupli_parent->obmat);
+ if (psys) {
+ if ((dupli_parent != NULL) && (dupli_object != NULL)) {
+ if (dupli_object->type & OB_DUPLICOLLECTION) {
+ copy_m4_m4(dupli_mat, dupli_parent->obmat);
+ }
+ else {
+ copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
+ invert_m4(dupli_mat);
+ mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ }
}
else {
- copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
- invert_m4(dupli_mat);
- mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ unit_m4(dupli_mat);
}
}
else {
- unit_m4(dupli_mat);
+ /* New hair object. */
+ copy_m4_m4(dupli_mat, object->obmat);
+ }
+
+ /* Get hair shape parameters. */
+ float hair_rad_shape, hair_rad_root, hair_rad_tip;
+ bool hair_close_tip;
+ if (psys) {
+ /* Old particle hair. */
+ ParticleSettings *part = psys->part;
+ hair_rad_shape = part->shape;
+ hair_rad_root = part->rad_root * part->rad_scale * 0.5f;
+ hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f;
+ hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
+ }
+ else {
+ /* TODO: implement for new hair object. */
+ hair_rad_shape = 1.0f;
+ hair_rad_root = 0.005f;
+ hair_rad_tip = 0.0f;
+ hair_close_tip = true;
}
DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
- DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1);
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[0]", dupli_mat[0]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[1]", dupli_mat[1]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[2]", dupli_mat[2]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[3]", dupli_mat[3]);
- DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f);
- DRW_shgroup_uniform_bool_copy(
- shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0);
- /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling
- * test. */
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
+ DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass
+ * culling test. */
GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
DRW_shgroup_call_no_cull(shgrp, geom, object);
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index c03b4822b1b..4d9eaf88a7d 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -79,6 +79,8 @@ typedef struct ParticleHairCache {
int point_len;
} ParticleHairCache;
+void particle_batch_cache_clear_hair(struct ParticleHairCache *hair_cache);
+
bool particles_ensure_procedural_data(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
@@ -86,4 +88,9 @@ bool particles_ensure_procedural_data(struct Object *object,
int subdiv,
int thickness_res);
+bool hair_ensure_procedural_data(struct Object *object,
+ struct ParticleHairCache **r_hair_cache,
+ int subdiv,
+ int thickness_res);
+
#endif /* __DRAW_HAIR_PRIVATE_H__ */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 618922d8544..df3a1e3da79 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -38,6 +38,7 @@
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_hair.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mball.h"
@@ -48,6 +49,8 @@
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
+#include "BKE_pointcloud.h"
+#include "BKE_volume.h"
#include "draw_manager.h"
#include "DNA_camera_types.h"
@@ -2653,6 +2656,15 @@ void DRW_engines_register(void)
BKE_gpencil_batch_cache_dirty_tag_cb = DRW_gpencil_batch_cache_dirty_tag;
BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
+
+ BKE_hair_batch_cache_dirty_tag_cb = DRW_hair_batch_cache_dirty_tag;
+ BKE_hair_batch_cache_free_cb = DRW_hair_batch_cache_free;
+
+ BKE_pointcloud_batch_cache_dirty_tag_cb = DRW_pointcloud_batch_cache_dirty_tag;
+ BKE_pointcloud_batch_cache_free_cb = DRW_pointcloud_batch_cache_free;
+
+ BKE_volume_batch_cache_dirty_tag_cb = DRW_volume_batch_cache_dirty_tag;
+ BKE_volume_batch_cache_free_cb = DRW_volume_batch_cache_free;
}
}