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.txt3
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c5
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h1
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders_extra.cc24
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c252
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl89
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl6
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c19
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h1
-rw-r--r--source/blender/draw/engines/workbench/shaders/infos/workbench_volume_info.hh1
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c1
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c26
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h5
-rw-r--r--source/blender/draw/engines/workbench/workbench_render.c4
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c19
-rw-r--r--source/blender/draw/intern/DRW_gpu_wrapper.hh3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curves.cc65
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c22
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c22
-rw-r--r--source/blender/draw/intern/draw_common.h41
-rw-r--r--source/blender/draw/intern/draw_curves.cc325
-rw-r--r--source/blender/draw/intern/draw_curves_private.h75
-rw-r--r--source/blender/draw/intern/draw_fluid.c97
-rw-r--r--source/blender/draw/intern/draw_hair.c97
-rw-r--r--source/blender/draw/intern/draw_hair_private.h11
-rw-r--r--source/blender/draw/intern/draw_manager.c46
-rw-r--r--source/blender/draw/intern/draw_manager.h4
-rw-r--r--source/blender/draw/intern/draw_manager_data.c10
-rw-r--r--source/blender/draw/intern/draw_shader.c24
-rw-r--r--source/blender/draw/intern/draw_shader.h5
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h16
-rw-r--r--source/blender/draw/intern/draw_volume.cc263
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc4
-rw-r--r--source/blender/draw/intern/shaders/common_attribute_lib.glsl12
-rw-r--r--source/blender/draw/intern/shaders/draw_object_infos_info.hh4
42 files changed, 1065 insertions, 582 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 6d3c203b076..8c54c923476 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SRC
intern/draw_cache_impl_volume.c
intern/draw_color_management.cc
intern/draw_common.c
+ intern/draw_curves.cc
intern/draw_debug.c
intern/draw_fluid.c
intern/draw_hair.c
@@ -98,6 +99,7 @@ set(SRC
intern/draw_texture_pool.cc
intern/draw_view.c
intern/draw_view_data.cc
+ intern/draw_volume.cc
intern/smaa_textures.c
engines/basic/basic_engine.c
engines/basic/basic_shader.c
@@ -194,6 +196,7 @@ set(SRC
intern/draw_color_management.h
intern/draw_common.h
intern/draw_common_shader_shared.h
+ intern/draw_curves_private.h
intern/draw_debug.h
intern/draw_hair_private.h
intern/draw_instance_data.h
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 81edee17c76..47e8f234a01 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -353,8 +353,6 @@ static void eevee_draw_scene(void *vedata)
EEVEE_renderpasses_draw_debug(vedata);
- EEVEE_volumes_free_smoke_textures();
-
stl->g_data->view_updated = false;
DRW_view_set_active(NULL);
@@ -574,7 +572,6 @@ static void eevee_render_to_image(void *vedata,
}
}
- EEVEE_volumes_free_smoke_textures();
EEVEE_motion_blur_data_free(&ved->stl->effects->motion_blur);
if (RE_engine_test_break(engine)) {
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 2e1b92de068..4f562dd9804 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -965,7 +965,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
txl->color = NULL;
DRW_render_instance_buffer_finish();
- DRW_hair_update();
+ DRW_curves_update();
}
static void eevee_lightbake_copy_irradiance(EEVEE_LightBake *lbake, LightCache *lcache)
@@ -1463,9 +1463,6 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
}
eevee_lightbake_delete_resources(lbake);
-
- /* Free GPU smoke textures and the smoke domain list correctly: See also T73921. */
- EEVEE_volumes_free_smoke_textures();
}
void EEVEE_lightbake_update_world_quick(EEVEE_ViewLayerData *sldata,
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index e3342508a14..2e0937dbe49 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -440,9 +440,9 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
DRW_render_instance_buffer_finish();
/* Need to be called after #DRW_render_instance_buffer_finish() */
- /* Also we weed to have a correct FBO bound for #DRW_hair_update. */
+ /* Also we weed to have a correct FBO bound for #DRW_curves_update. */
GPU_framebuffer_bind(vedata->fbl->main_fb);
- DRW_hair_update();
+ DRW_curves_update();
DRW_cache_restart();
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 9f97dacf9fe..ee336326166 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -1558,7 +1558,6 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_volumes_free_smoke_textures(void);
void EEVEE_volumes_free(void);
/* eevee_effects.c */
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 47e2b95f367..bef19c589c2 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -538,9 +538,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
DRW_render_instance_buffer_finish();
/* Need to be called after DRW_render_instance_buffer_finish() */
- /* Also we weed to have a correct FBO bound for DRW_hair_update */
+ /* Also we weed to have a correct FBO bound for DRW_curves_update */
GPU_framebuffer_bind(fbl->main_fb);
- DRW_hair_update();
+ DRW_curves_update();
/* Sort transparents before the loop. */
DRW_pass_sort_shgroup_z(psl->transparent_pass);
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 4e4a2a9eb8e..85cc7f65126 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -1487,6 +1487,10 @@ struct GPUMaterial *EEVEE_material_get(
GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred);
int status = GPU_material_status(mat);
+ /* Return null material and bypass drawing for volume shaders. */
+ if ((options & VAR_MAT_VOLUME) && status != GPU_MAT_SUCCESS) {
+ return NULL;
+ }
switch (status) {
case GPU_MAT_SUCCESS:
break;
diff --git a/source/blender/draw/engines/eevee/eevee_shaders_extra.cc b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc
index bb1a0b0abe4..05577944140 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders_extra.cc
+++ b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc
@@ -81,7 +81,7 @@ void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
const bool do_fragment_attrib_load = is_background || is_volume;
if (is_hair && !info.vertex_out_interfaces_.is_empty()) {
- /** Hair attributes comme from sampler buffer. Transfer attributes to sampler. */
+ /** Hair attributes come from sampler buffer. Transfer attributes to sampler. */
for (auto &input : info.vertex_inputs_) {
info.sampler(0, ImageType::FLOAT_BUFFER, input.name, Frequency::BATCH);
}
@@ -97,12 +97,26 @@ void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
}
attr_load << "};\n";
attr_load << iface.name << " " << iface.instance_name << ";\n";
- /* Global vars just to make code valid. Only Orco is supported. */
- for (const ShaderCreateInfo::VertIn &in : info.vertex_inputs_) {
- attr_load << in.type << " " << in.name << ";\n";
+ if (!is_volume) {
+ /* Global vars just to make code valid. Only Orco is supported. */
+ for (const ShaderCreateInfo::VertIn &in : info.vertex_inputs_) {
+ attr_load << in.type << " " << in.name << ";\n";
+ }
}
info.vertex_out_interfaces_.clear();
}
+ if (is_volume) {
+ /** Volume grid attributes come from 3D textures. Transfer attributes to samplers. */
+ for (auto &input : info.vertex_inputs_) {
+ info.sampler(0, ImageType::FLOAT_3D, input.name, Frequency::BATCH);
+ }
+ info.additional_info("draw_volume_infos");
+ /* Do not add twice. */
+ if (!GPU_material_flag_get(gpumat, GPU_MATFLAG_OBJECT_INFO)) {
+ info.additional_info("draw_object_infos");
+ }
+ info.vertex_inputs_.clear();
+ }
if (!is_volume) {
info.define("EEVEE_GENERATED_INTERFACE");
@@ -137,7 +151,7 @@ void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
}
frag_gen << "Closure nodetree_exec()\n";
frag_gen << "{\n";
- if (GPU_material_is_volume_shader(gpumat)) {
+ if (is_volume) {
frag_gen << ((codegen.volume) ? codegen.volume : "return CLOSURE_DEFAULT;\n");
}
else {
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 6a0c9fb36df..b8bef61f8b1 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -43,35 +43,8 @@ static struct {
GPUTexture *dummy_scatter;
GPUTexture *dummy_transmit;
-
- /* List of all fluid simulation / smoke domains rendered within this frame. */
- ListBase smoke_domains;
} e_data = {NULL}; /* Engine data */
-static void eevee_create_textures_volumes(void)
-{
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- e_data.dummy_zero = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, zero);
-
- const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- e_data.dummy_one = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, one);
-
- const float flame = 0.0f;
- e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame);
-}
-
-static GPUTexture *eevee_volume_default_texture(eGPUVolumeDefaultValue default_value)
-{
- switch (default_value) {
- case GPU_VOLUME_DEFAULT_0:
- return e_data.dummy_zero;
- case GPU_VOLUME_DEFAULT_1:
- return e_data.dummy_one;
- }
-
- return e_data.dummy_zero;
-}
-
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
@@ -227,11 +200,6 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Scene *scene = draw_ctx->scene;
DRWShadingGroup *grp = NULL;
- /* Textures */
- if (!e_data.dummy_zero) {
- eevee_create_textures_volumes();
- }
-
/* Quick breakdown of the Volumetric rendering:
*
* The rendering is separated in 4 stages:
@@ -268,7 +236,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME);
- if (GPU_material_has_volume_output(mat)) {
+ if (mat && GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
}
@@ -283,11 +251,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
/* Fix principle volumetric not working with world materials. */
- ListBase gpu_grids = GPU_material_volume_grids(mat);
- LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
- DRW_shgroup_uniform_texture(
- grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
- }
+ grp = DRW_shgroup_volume_create_sub(NULL, NULL, grp, mat);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -299,187 +263,17 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_create(EEVEE_shaders_volumes_clear_sh_get(), psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
}
}
-static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWShadingGroup *grp)
-{
- 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) {
- const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(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;
- }
- }
- }
-
- /* Bail out of no grids to render. */
- if (first_drw_grid == NULL) {
- return false;
- }
-
- /* 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. */
- const 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);
- }
- 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);
- }
-
- /* 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});
-
- /* 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) {
- const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, gpu_grid->name);
- DRWVolumeGrid *drw_grid = (volume_grid) ?
- DRW_volume_batch_cache_get_grid(volume, volume_grid) :
- NULL;
-
- /* Handle 3 cases here:
- * - Grid exists and texture was loaded -> use texture.
- * - Grid exists but has zero size or failed to load -> use zero.
- * - Grid does not exist -> use default value. */
- GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture :
- (volume_grid) ? e_data.dummy_zero :
- eevee_volume_default_texture(gpu_grid->default_value);
-
- DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex);
-
- if (drw_grid && multiple_transforms) {
- /* Specify per-volume transform 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);
- }
- }
-
- return true;
-}
-
-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;
-
- /* Smoke Simulation */
- if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) &&
- (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) &&
- ((FluidModifierData *)md)->domain != NULL) {
- FluidModifierData *fmd = (FluidModifierData *)md;
- FluidDomainSettings *fds = fmd->domain;
-
- /* Don't try to show liquid domains here. */
- if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) {
- return false;
- }
-
- /* Don't show smoke before simulation starts, this could be made an option in the future. */
- /* (sebbas): Always show smoke for manta */
-#if 0
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const bool show_smoke = ((int)DEG_get_ctime(draw_ctx->depsgraph) >=
- *fds->point_cache[0]->startframe);
-#endif
-
- if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS) /* && show_smoke */) {
- DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE);
- BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(fmd));
- }
-
- LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
- if (STREQ(gpu_grid->name, "density")) {
- DRW_shgroup_uniform_texture_ref(
- grp, gpu_grid->sampler_name, fds->tex_density ? &fds->tex_density : &e_data.dummy_one);
- }
- else if (STREQ(gpu_grid->name, "color")) {
- DRW_shgroup_uniform_texture_ref(
- grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_one);
- }
- else if (STR_ELEM(gpu_grid->name, "flame", "temperature")) {
- DRW_shgroup_uniform_texture_ref(
- grp, gpu_grid->sampler_name, fds->tex_flame ? &fds->tex_flame : &e_data.dummy_flame);
- }
- else {
- DRW_shgroup_uniform_texture(
- grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
- }
- }
-
- /* Constant Volume color. */
- bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
- (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0);
-
- DRW_shgroup_uniform_vec3(
- grp, "volumeColor", (use_constant_color) ? fds->active_color : white, 1);
-
- /* Output is such that 0..1 maps to 0..1000K */
- DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &fds->flame_ignition, 1);
- }
- else {
- LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
- DRW_shgroup_uniform_texture(
- grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
- }
- }
-
- /* 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,
@@ -506,15 +300,22 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH;
struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
- eGPUMaterialStatus status = GPU_material_status(mat);
/* If shader failed to compile or is currently compiling. */
- if (status != GPU_MAT_SUCCESS) {
+ if (mat == NULL) {
return;
}
+ /* TODO(fclem): Reuse main shading group to avoid shading binding cost just like for surface
+ * shaders. */
DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
+ grp = DRW_shgroup_volume_create_sub(scene, ob, grp, mat);
+
+ if (grp == NULL) {
+ return;
+ }
+
/* 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);
@@ -522,22 +323,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
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", sldata->renderpass_ubo.combined);
-
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. */
/* TODO: Preemptive culling. */
DRW_shgroup_call_procedural_triangles(grp, ob, sldata->common_data.vol_tex_size[2]);
@@ -753,16 +539,6 @@ void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
}
}
-void EEVEE_volumes_free_smoke_textures(void)
-{
- /* Free Smoke Textures after rendering */
- LISTBASE_FOREACH (LinkData *, link, &e_data.smoke_domains) {
- FluidModifierData *fmd = (FluidModifierData *)link->data;
- DRW_smoke_free(fmd);
- }
- BLI_freelistN(&e_data.smoke_domains);
-}
-
void EEVEE_volumes_free(void)
{
DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index 0e8e8dd9d01..ab0f4d6bec8 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -144,3 +144,13 @@ vec3 attr_load_uv(vec3 attr)
return attr;
}
#endif
+
+/* Passthrough. */
+float attr_load_temperature_post(float attr)
+{
+ return attr;
+}
+vec4 attr_load_color_post(vec4 attr)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
index 9ad7a4fdbc1..79ec3807d0b 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
@@ -179,3 +179,13 @@ vec3 attr_load_uv(vec3 attr)
{
return vec3(0);
}
+
+/* Passthrough. */
+float attr_load_temperature_post(float attr)
+{
+ return attr;
+}
+vec4 attr_load_color_post(vec4 attr)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
index 6c6b810422b..49c18832f72 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
@@ -157,3 +157,13 @@ vec3 attr_load_uv(vec3 attr)
return attr;
}
#endif
+
+/* Passthrough. */
+float attr_load_temperature_post(float attr)
+{
+ return attr;
+}
+vec4 attr_load_color_post(vec4 attr)
+{
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index e0a79872928..914261d7f59 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -4,17 +4,13 @@
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
-#ifdef MESH_SHADER
-uniform vec3 volumeOrcoLoc;
-uniform vec3 volumeOrcoSize;
-uniform mat4 volumeObjectToTexture;
-uniform float volumeDensityScale = 1.0;
-#endif
+/* Store volumetric properties into the froxel textures. */
flat in int slice;
/* Warning: these are not attributes, these are global vars. */
vec3 worldPosition = vec3(0.0);
+vec3 objectPosition = vec3(0.0);
vec3 viewPosition = vec3(0.0);
vec3 viewNormal = vec3(0.0);
vec3 volumeOrco = vec3(0.0);
@@ -24,9 +20,9 @@ layout(location = 1) out vec4 volumeExtinction;
layout(location = 2) out vec4 volumeEmissive;
layout(location = 3) out vec4 volumePhase;
-/* Store volumetric properties into the froxel textures. */
+int attr_id;
-#ifdef MESH_SHADER
+#ifndef CLEAR
GlobalData init_globals(void)
{
GlobalData surf;
@@ -80,10 +76,8 @@ void main()
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
- volumeOrco = point_world_to_object(worldPosition);
- /* TODO: redundant transform */
- volumeOrco = (volumeOrco - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0);
- volumeOrco = (volumeObjectToTexture * vec4(volumeOrco, 1.0)).xyz;
+ objectPosition = point_world_to_object(worldPosition);
+ volumeOrco = OrcoTexCoFactors[0].xyz + objectPosition * OrcoTexCoFactors[1].xyz;
if (any(lessThan(volumeOrco, vec3(0.0))) || any(greaterThan(volumeOrco, vec3(1.0)))) {
/* Note: Discard is not an explicit return in Metal prior to versions 2.3.
@@ -100,15 +94,13 @@ void main()
volumeEmissive = vec4(0.0, 0.0, 0.0, 1.0);
volumePhase = vec4(0.0, 0.0, 0.0, 0.0);
#else
-# ifdef MESH_SHADER
g_data = init_globals();
attrib_load();
-# endif
Closure cl = nodetree_exec();
# ifdef MESH_SHADER
- cl.scatter *= volumeDensityScale;
- cl.absorption *= volumeDensityScale;
- cl.emission *= volumeDensityScale;
+ cl.scatter *= drw_volume.density_scale;
+ cl.absorption *= drw_volume.density_scale;
+ cl.emission *= drw_volume.density_scale;
# endif
volumeScattering = vec4(cl.scatter, 1.0);
@@ -124,35 +116,72 @@ void main()
#endif
}
-vec3 attr_load_orco(vec4 orco)
+vec3 grid_coordinates()
+{
+ vec3 co = volumeOrco;
+#ifdef MESH_SHADER
+ /* Optional per-grid transform. */
+ if (drw_volume.grids_xform[attr_id][3][3] != 0.0) {
+ co = (drw_volume.grids_xform[attr_id] * vec4(objectPosition, 1.0)).xyz;
+ }
+#endif
+ attr_id += 1;
+ return co;
+}
+
+vec3 attr_load_orco(sampler3D orco)
{
+ attr_id += 1;
return volumeOrco;
}
-vec4 attr_load_tangent(vec4 tangent)
+vec4 attr_load_tangent(sampler3D tangent)
{
+ attr_id += 1;
return vec4(0);
}
-vec4 attr_load_vec4(vec4 attr)
+vec4 attr_load_vec4(sampler3D tex)
{
- return vec4(0);
+ return texture(tex, grid_coordinates());
}
-vec3 attr_load_vec3(vec3 attr)
+vec3 attr_load_vec3(sampler3D tex)
{
- return vec3(0);
+ return texture(tex, grid_coordinates()).rgb;
}
-vec2 attr_load_vec2(vec2 attr)
+vec2 attr_load_vec2(sampler3D tex)
{
- return vec2(0);
+ return texture(tex, grid_coordinates()).rg;
}
-float attr_load_float(float attr)
+float attr_load_float(sampler3D tex)
{
- return 0.0;
+ return texture(tex, grid_coordinates()).r;
}
-vec4 attr_load_color(vec4 attr)
+vec4 attr_load_color(sampler3D tex)
{
- return vec4(0);
+ return texture(tex, grid_coordinates());
}
-vec3 attr_load_uv(vec3 attr)
+vec3 attr_load_uv(sampler3D attr)
{
+ attr_id += 1;
return vec3(0);
}
+
+/* TODO(@fclem): These implementation details should concern the DRWManager and not be a fix on
+ * the engine side. But as of now, the engines are reponsible for loading the attributes. */
+float attr_load_temperature_post(float attr)
+{
+#ifdef MESH_SHADER
+ /* Bring the into standard range without having to modify the grid values */
+ attr = (attr > 0.01) ? (attr * drw_volume.temperature_mul + drw_volume.temperature_bias) : 0.0;
+#endif
+ return attr;
+}
+vec4 attr_load_color_post(vec4 attr)
+{
+#ifdef MESH_SHADER
+ /* Density is premultiplied for interpolation, divide it out here. */
+ attr.rgb *= safe_rcp(attr.a);
+ attr.rgb *= drw_volume.color_mul.rgb;
+ attr.a = 1.0;
+#endif
+ return attr;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
index 26b60c992e1..527bbd18896 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
@@ -11,10 +11,8 @@ uniform sampler3D volumeScattering; /* Result of the scatter step */
uniform sampler3D volumeExtinction;
#ifdef USE_VOLUME_OPTI
-uniform layout(r11f_g11f_b10f)
-writeonly restrict image3D finalScattering_img;
-uniform layout(r11f_g11f_b10f)
-writeonly restrict image3D finalTransmittance_img;
+uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalScattering_img;
+uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img;
vec3 finalScattering;
vec3 finalTransmittance;
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index abcca5525c7..5d8ba06e181 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1474,23 +1474,6 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
}
if (draw_velocity || show_gridlines) {
- BLI_addtail(&data->stl->pd->smoke_domains, BLI_genericNodeN(fmd));
- }
-}
-
-static void OVERLAY_volume_free_smoke_textures(OVERLAY_Data *data)
-{
- /* Free Smoke Textures after rendering */
- /* XXX This is a waste of processing and GPU bandwidth if nothing
- * is updated. But the problem is since Textures are stored in the
- * modifier we don't want them to take precious VRAM if the
- * modifier is not used for display. We should share them for
- * all viewport in a redraw at least. */
- LinkData *link;
- while ((link = BLI_pophead(&data->stl->pd->smoke_domains))) {
- FluidModifierData *fmd = (FluidModifierData *)link->data;
- DRW_smoke_free_velocity(fmd);
- MEM_freeN(link);
}
}
@@ -1624,8 +1607,6 @@ void OVERLAY_extra_draw(OVERLAY_Data *vedata)
void OVERLAY_extra_in_front_draw(OVERLAY_Data *vedata)
{
DRW_draw_pass(vedata->psl->extra_ps[1]);
-
- OVERLAY_volume_free_smoke_textures(vedata);
}
void OVERLAY_extra_centers_draw(OVERLAY_Data *vedata)
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 71b6c9424e6..4c933e08a57 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -304,7 +304,6 @@ typedef struct OVERLAY_PrivateData {
DRWView *view_edit_curves_points;
/** TODO: get rid of this. */
- ListBase smoke_domains;
ListBase bg_movie_clips;
/** Two instances for in_front option and without. */
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_volume_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_volume_info.hh
index 5d098d61dbf..698c7d1a8b7 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_volume_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_volume_info.hh
@@ -55,7 +55,6 @@ GPU_SHADER_CREATE_INFO(workbench_volume_coba)
GPU_SHADER_CREATE_INFO(workbench_volume_no_coba)
.sampler(4, ImageType::FLOAT_3D, "shadowTexture")
- .sampler(5, ImageType::UINT_2D, "transferTexture")
.push_constant(Type::VEC3, "activeColor");
/** \} */
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index f4e042933d1..f7f156e5297 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -163,7 +163,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->taa_sample_len = workbench_antialiasing_sample_count_get(wpd);
wpd->volumes_do = false;
- BLI_listbase_clear(&wpd->smoke_domains);
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
* But this is a workaround for a missing update tagging. */
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 566fd30096d..fb20bde2f65 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -271,6 +271,18 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
BKE_pbvh_is_drawing_set(ob->sculpt->pbvh, is_sculpt_pbvh);
}
+ bool has_color = false;
+
+ if (me) {
+ const CustomData *cd_vdata = workbench_mesh_get_vert_custom_data(me);
+ const CustomData *cd_ldata = workbench_mesh_get_loop_custom_data(me);
+
+ has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
+ CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) ||
+ CustomData_has_layer(cd_ldata, CD_PROP_COLOR) ||
+ CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR));
+ }
+
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
if (ob->dt < OB_TEXTURE) {
color_type = V3D_SHADING_MATERIAL_COLOR;
@@ -285,14 +297,6 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
color_type = V3D_SHADING_OBJECT_COLOR;
}
else {
- const CustomData *cd_vdata = workbench_mesh_get_vert_custom_data(me);
- const CustomData *cd_ldata = workbench_mesh_get_loop_custom_data(me);
-
- bool has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
- CustomData_has_layer(cd_vdata, CD_MLOOPCOL) ||
- CustomData_has_layer(cd_ldata, CD_PROP_COLOR) ||
- CustomData_has_layer(cd_ldata, CD_MLOOPCOL));
-
if (!has_color) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
@@ -314,7 +318,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
*r_texpaint_mode = true;
}
}
- else if (is_vertpaint_mode && me && CustomData_has_layer(ldata, CD_MLOOPCOL)) {
+ else if (is_vertpaint_mode && me && has_color) {
color_type = V3D_SHADING_VERTEX_COLOR;
}
}
@@ -613,10 +617,8 @@ static void workbench_draw_scene(void *ved)
workbench_draw_finish(vedata);
}
-void workbench_draw_finish(void *ved)
+void workbench_draw_finish(void *UNUSED(ved))
{
- WORKBENCH_Data *vedata = ved;
- workbench_volume_draw_finish(vedata);
/* Reset default view. */
DRW_view_set_active(NULL);
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 727b771ee08..492bce1e571 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -324,10 +324,6 @@ typedef struct WORKBENCH_PrivateData {
/** Index of current material inside the material chunk. Only for material coloring mode. */
int material_index;
- /* Volumes */
- /** List of smoke domain textures to free after drawing. */
- ListBase smoke_domains;
-
/* Depth of Field */
/** Depth of field temp buffers. */
struct GPUTexture *dof_blur_tx;
@@ -533,7 +529,6 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
struct ModifierData *md,
eV3DShadingColorType color_type);
void workbench_volume_draw_pass(WORKBENCH_Data *vedata);
-void workbench_volume_draw_finish(WORKBENCH_Data *vedata);
/* workbench_engine.c */
diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c
index 72de3fe298a..1279682e899 100644
--- a/source/blender/draw/engines/workbench/workbench_render.c
+++ b/source/blender/draw/engines/workbench/workbench_render.c
@@ -170,9 +170,9 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer
DRW_render_instance_buffer_finish();
- /* Also we weed to have a correct FBO bound for #DRW_hair_update */
+ /* Also we weed to have a correct FBO bound for #DRW_curves_update */
GPU_framebuffer_bind(dfbl->default_fb);
- DRW_hair_update();
+ DRW_curves_update();
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f);
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index c6f40c5d6bb..2c902e9b627 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -178,8 +178,6 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
else {
DRW_shgroup_call(grp, DRW_cache_cube_get(), ob);
}
-
- BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(fmd));
}
static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd,
@@ -334,20 +332,3 @@ void workbench_volume_draw_pass(WORKBENCH_Data *vedata)
DRW_draw_pass(psl->volume_ps);
}
}
-
-void workbench_volume_draw_finish(WORKBENCH_Data *vedata)
-{
- WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
-
- /* Free Smoke Textures after rendering */
- /* XXX This is a waste of processing and GPU bandwidth if nothing
- * is updated. But the problem is since Textures are stored in the
- * modifier we don't want them to take precious VRAM if the
- * modifier is not used for display. We should share them for
- * all viewport in a redraw at least. */
- LISTBASE_FOREACH (LinkData *, link, &wpd->smoke_domains) {
- FluidModifierData *fmd = (FluidModifierData *)link->data;
- DRW_smoke_free(fmd);
- }
- BLI_freelistN(&wpd->smoke_domains);
-}
diff --git a/source/blender/draw/intern/DRW_gpu_wrapper.hh b/source/blender/draw/intern/DRW_gpu_wrapper.hh
index ed94c485b32..d7e752a43f4 100644
--- a/source/blender/draw/intern/DRW_gpu_wrapper.hh
+++ b/source/blender/draw/intern/DRW_gpu_wrapper.hh
@@ -53,6 +53,8 @@
*
*/
+#include "DRW_render.h"
+
#include "MEM_guardedalloc.h"
#include "draw_texture_pool.h"
@@ -61,6 +63,7 @@
#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "BLI_utility_mixins.hh"
+#include "BLI_vector.hh"
#include "GPU_framebuffer.h"
#include "GPU_storage_buffer.h"
diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc
index b084a5e5945..f2742f3bcc7 100644
--- a/source/blender/draw/intern/draw_cache_impl_curves.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curves.cc
@@ -29,9 +29,11 @@
#include "GPU_material.h"
#include "GPU_texture.h"
+#include "DRW_render.h"
+
#include "draw_cache_impl.h" /* own include */
#include "draw_cache_inline.h"
-#include "draw_hair_private.h" /* own include */
+#include "draw_curves_private.h" /* own include */
using blender::float3;
using blender::IndexRange;
@@ -41,7 +43,7 @@ using blender::Span;
/* Curves GPUBatch Cache */
struct CurvesBatchCache {
- ParticleHairCache hair;
+ CurvesEvalCache curves_cache;
GPUBatch *edit_points;
@@ -70,6 +72,28 @@ static void curves_batch_cache_init(Curves &curves)
cache->is_dirty = false;
}
+static void curves_batch_cache_clear_data(CurvesEvalCache &curves_cache)
+{
+ /* TODO: more granular update tagging. */
+ GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_point_buf);
+ GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_length_buf);
+ DRW_TEXTURE_FREE_SAFE(curves_cache.point_tex);
+ DRW_TEXTURE_FREE_SAFE(curves_cache.length_tex);
+
+ GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_buf);
+ GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_seg_buf);
+ DRW_TEXTURE_FREE_SAFE(curves_cache.strand_tex);
+ DRW_TEXTURE_FREE_SAFE(curves_cache.strand_seg_tex);
+
+ for (int i = 0; i < MAX_HAIR_SUBDIV; i++) {
+ GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].proc_buf);
+ DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].proc_tex);
+ for (int j = 0; j < MAX_THICKRES; j++) {
+ GPU_BATCH_DISCARD_SAFE(curves_cache.final[i].proc_hairs[j]);
+ }
+ }
+}
+
static void curves_batch_cache_clear(Curves &curves)
{
CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache);
@@ -77,7 +101,8 @@ static void curves_batch_cache_clear(Curves &curves)
return;
}
- particle_batch_cache_clear_hair(&cache->hair);
+ curves_batch_cache_clear_data(cache->curves_cache);
+
GPU_BATCH_DISCARD_SAFE(cache->edit_points);
}
@@ -116,10 +141,9 @@ void DRW_curves_batch_cache_free(Curves *curves)
MEM_SAFE_FREE(curves->batch_cache);
}
-static void ensure_seg_pt_count(const Curves &curves, ParticleHairCache &curves_cache)
+static void ensure_seg_pt_count(const Curves &curves, CurvesEvalCache &curves_cache)
{
- if ((curves_cache.pos != nullptr && curves_cache.indices != nullptr) ||
- (curves_cache.proc_point_buf != nullptr)) {
+ if (curves_cache.proc_point_buf != nullptr) {
return;
}
@@ -169,7 +193,7 @@ static void curves_batch_cache_fill_segments_proc_pos(const Curves &curves_id,
}
static void curves_batch_cache_ensure_procedural_pos(Curves &curves,
- ParticleHairCache &cache,
+ CurvesEvalCache &cache,
GPUMaterial *gpu_material)
{
if (cache.proc_point_buf == nullptr || DRW_vbo_requested(cache.proc_point_buf)) {
@@ -229,7 +253,7 @@ static void curves_batch_cache_fill_strands_data(const Curves &curves_id,
}
static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves,
- ParticleHairCache &cache)
+ CurvesEvalCache &cache)
{
GPUVertBufRaw data_step, seg_step;
@@ -259,7 +283,7 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves,
cache.proc_strand_seg_buf);
}
-static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache &cache, int subdiv)
+static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &cache, int subdiv)
{
/* Same format as point_tex. */
GPUVertFormat format = {0};
@@ -296,7 +320,7 @@ static void curves_batch_cache_fill_segments_indices(const Curves &curves,
}
static void curves_batch_cache_ensure_procedural_indices(Curves &curves,
- ParticleHairCache &cache,
+ CurvesEvalCache &cache,
const int thickness_res,
const int subdiv)
{
@@ -330,7 +354,7 @@ static void curves_batch_cache_ensure_procedural_indices(Curves &curves,
}
bool curves_ensure_procedural_data(Object *object,
- ParticleHairCache **r_hair_cache,
+ CurvesEvalCache **r_hair_cache,
GPUMaterial *gpu_material,
const int subdiv,
const int thickness_res)
@@ -339,30 +363,31 @@ bool curves_ensure_procedural_data(Object *object,
Curves &curves = *static_cast<Curves *>(object->data);
CurvesBatchCache &cache = curves_batch_cache_get(curves);
- *r_hair_cache = &cache.hair;
+ *r_hair_cache = &cache.curves_cache;
const int steps = 3; /* TODO: don't hard-code? */
(*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == nullptr) {
- ensure_seg_pt_count(curves, cache.hair);
- curves_batch_cache_ensure_procedural_pos(curves, cache.hair, gpu_material);
+ ensure_seg_pt_count(curves, cache.curves_cache);
+ curves_batch_cache_ensure_procedural_pos(curves, cache.curves_cache, gpu_material);
need_ft_update = true;
}
/* Refreshed if active layer or custom data changes. */
if ((*r_hair_cache)->strand_tex == nullptr) {
- curves_batch_cache_ensure_procedural_strand_data(curves, cache.hair);
+ curves_batch_cache_ensure_procedural_strand_data(curves, cache.curves_cache);
}
/* Refreshed only on subdiv count change. */
if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) {
- curves_batch_cache_ensure_procedural_final_points(cache.hair, subdiv);
+ curves_batch_cache_ensure_procedural_final_points(cache.curves_cache, subdiv);
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
- curves_batch_cache_ensure_procedural_indices(curves, cache.hair, thickness_res, subdiv);
+ curves_batch_cache_ensure_procedural_indices(
+ curves, cache.curves_cache, thickness_res, subdiv);
}
return need_ft_update;
@@ -385,10 +410,10 @@ void DRW_curves_batch_cache_create_requested(const Object *ob)
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
if (DRW_batch_requested(cache.edit_points, GPU_PRIM_POINTS)) {
- DRW_vbo_request(cache.edit_points, &cache.hair.proc_point_buf);
+ DRW_vbo_request(cache.edit_points, &cache.curves_cache.proc_point_buf);
}
- if (DRW_vbo_requested(cache.hair.proc_point_buf)) {
- curves_batch_cache_ensure_procedural_pos(*curves, cache.hair, nullptr);
+ if (DRW_vbo_requested(cache.curves_cache.proc_point_buf)) {
+ curves_batch_cache_ensure_procedural_pos(*curves, cache.curves_cache, nullptr);
}
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index c4fa60ef51d..e4aec17eb69 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -518,15 +518,17 @@ static uint mesh_cd_calc_gpu_layers_vcol_used(const Mesh *me_query,
domain = ATTR_DOMAIN_POINT;
layer_i = CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, name);
- layer_i = layer_i == -1 ? CustomData_get_named_layer_index(cd_vdata, CD_MLOOPCOL, name) :
- layer_i;
+ layer_i = layer_i == -1 ?
+ CustomData_get_named_layer_index(cd_vdata, CD_PROP_BYTE_COLOR, name) :
+ layer_i;
if (layer_i == -1) {
domain = ATTR_DOMAIN_CORNER;
layer_i = layer_i == -1 ? CustomData_get_named_layer_index(cd_ldata, CD_PROP_COLOR, name) :
layer_i;
- layer_i = layer_i == -1 ? CustomData_get_named_layer_index(cd_ldata, CD_MLOOPCOL, name) :
- layer_i;
+ layer_i = layer_i == -1 ?
+ CustomData_get_named_layer_index(cd_ldata, CD_PROP_BYTE_COLOR, name) :
+ layer_i;
}
/* Note: this is not the same as the layer_i below. */
@@ -610,17 +612,17 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
}
if (layer == -1) {
- layer = CustomData_get_named_layer(cd_vdata, CD_MLOOPCOL, name);
+ layer = CustomData_get_named_layer(cd_vdata, CD_PROP_BYTE_COLOR, name);
if (layer != -1) {
- type = CD_MLOOPCOL;
+ type = CD_PROP_BYTE_COLOR;
domain = ATTR_DOMAIN_POINT;
}
}
if (layer == -1) {
- layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
+ layer = CustomData_get_named_layer(cd_ldata, CD_PROP_BYTE_COLOR, name);
if (layer != -1) {
- type = CD_MLOOPCOL;
+ type = CD_PROP_BYTE_COLOR;
domain = ATTR_DOMAIN_CORNER;
}
}
@@ -700,11 +702,11 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
}
/* Note: attr->type will always be CD_PROP_COLOR even for
- * CD_MLOOPCOL layers, see node_shader_gpu_vertex_color in
+ * CD_PROP_BYTE_COLOR layers, see node_shader_gpu_vertex_color in
* node_shader_vertex_color.cc.
*/
case CD_MCOL:
- case CD_MLOOPCOL:
+ case CD_PROP_BYTE_COLOR:
case CD_PROP_COLOR: {
int vcol_bit = mesh_cd_calc_gpu_layers_vcol_used(&me_query, cd_vdata, cd_ldata, name);
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index c6b56723818..0f1ab967ca5 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -164,7 +164,7 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
}
-void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
+static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
/* TODO: more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
@@ -822,10 +822,11 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
render_uv = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
}
- if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
- cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
- active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
- render_col = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
+ if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) {
+ cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata,
+ CD_PROP_BYTE_COLOR);
+ active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR);
+ render_col = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR);
}
}
@@ -891,7 +892,7 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
+ const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR, i);
GPU_vertformat_safe_attr_name(name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
int n = 0;
@@ -1162,9 +1163,9 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
}
- if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
- num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
- active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
+ if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) {
+ num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR);
+ active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR);
}
}
@@ -1195,7 +1196,8 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
for (int i = 0; i < num_col_layers; i++) {
char uuid[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
+ const char *name = CustomData_get_layer_name(
+ &psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR, i);
GPU_vertformat_safe_attr_name(name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_snprintf(uuid, sizeof(uuid), "c%s", attr_safe_name);
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index d302140d9ac..779ac43178c 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -21,6 +21,8 @@ struct Object;
struct ParticleSystem;
struct RegionView3D;
struct ViewLayer;
+struct Scene;
+struct DRWData;
/* Keep in sync with globalsBlock in shaders */
BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16)
@@ -54,16 +56,12 @@ struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
struct DRWShadingGroup *shgrp,
struct GPUMaterial *gpu_material);
-struct DRWShadingGroup *DRW_shgroup_curves_create_sub(struct Object *object,
- struct DRWShadingGroup *shgrp,
- struct GPUMaterial *gpu_material);
/**
* \note Only valid after #DRW_hair_update().
*/
struct GPUVertBuf *DRW_hair_pos_buffer_get(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md);
-struct GPUVertBuf *DRW_curves_pos_buffer_get(struct Object *object);
void DRW_hair_duplimat_get(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
@@ -73,6 +71,37 @@ void DRW_hair_init(void);
void DRW_hair_update(void);
void DRW_hair_free(void);
+/* draw_curves.cc */
+
+/**
+ * \note Only valid after #DRW_curves_update().
+ */
+struct GPUVertBuf *DRW_curves_pos_buffer_get(struct Object *object);
+
+struct DRWShadingGroup *DRW_shgroup_curves_create_sub(struct Object *object,
+ struct DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpu_material);
+
+void DRW_curves_init(void);
+void DRW_curves_update(void);
+void DRW_curves_free(void);
+
+/* draw_volume.cc */
+
+/**
+ * Add attributes bindings of volume grids to an existing shading group.
+ * No draw call is added so the caller can decide how to use the data.
+ * \return nullptr if there is something to draw.
+ */
+struct DRWShadingGroup *DRW_shgroup_volume_create_sub(struct Scene *scene,
+ struct Object *ob,
+ struct DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpu_material);
+
+void DRW_volume_init(struct DRWData *drw_data);
+void DRW_volume_ubos_pool_free(void *pool);
+void DRW_volume_free(void);
+
/* draw_fluid.c */
/* Fluid simulation. */
@@ -83,7 +112,9 @@ void DRW_fluid_ensure_flags(struct FluidModifierData *fmd);
void DRW_fluid_ensure_range_field(struct FluidModifierData *fmd);
void DRW_smoke_free(struct FluidModifierData *fmd);
-void DRW_smoke_free_velocity(struct FluidModifierData *fmd);
+
+void DRW_smoke_init(struct DRWData *drw_data);
+void DRW_smoke_exit(struct DRWData *drw_data);
/* draw_common.c */
diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc
new file mode 100644
index 00000000000..88118361115
--- /dev/null
+++ b/source/blender/draw/intern/draw_curves.cc
@@ -0,0 +1,325 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2017 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Contains procedural GPU hair drawing methods.
+ */
+
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_customdata_types.h"
+
+#include "GPU_batch.h"
+#include "GPU_capabilities.h"
+#include "GPU_compute.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+#include "GPU_vertex_buffer.h"
+
+#include "DRW_render.h"
+
+#include "draw_hair_private.h"
+#include "draw_shader.h"
+
+#ifndef __APPLE__
+# define USE_TRANSFORM_FEEDBACK
+# define USE_COMPUTE_SHADERS
+#endif
+
+BLI_INLINE eParticleRefineShaderType drw_curves_shader_type_get()
+{
+#ifdef USE_COMPUTE_SHADERS
+ if (GPU_compute_shader_support() && GPU_shader_storage_buffer_objects_support()) {
+ return PART_REFINE_SHADER_COMPUTE;
+ }
+#endif
+#ifdef USE_TRANSFORM_FEEDBACK
+ return PART_REFINE_SHADER_TRANSFORM_FEEDBACK;
+#endif
+ return PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND;
+}
+
+#ifndef USE_TRANSFORM_FEEDBACK
+struct CurvesEvalCall {
+ struct CurvesEvalCall *next;
+ GPUVertBuf *vbo;
+ DRWShadingGroup *shgrp;
+ uint vert_len;
+};
+
+static CurvesEvalCall *g_tf_calls = nullptr;
+static int g_tf_id_offset;
+static int g_tf_target_width;
+static int g_tf_target_height;
+#endif
+
+static GPUVertBuf *g_dummy_vbo = nullptr;
+static GPUTexture *g_dummy_texture = nullptr;
+static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in the future */
+
+static GPUShader *curves_eval_shader_get(CurvesEvalShader type)
+{
+ return DRW_shader_curves_refine_get(type, drw_curves_shader_type_get());
+}
+
+void DRW_curves_init(void)
+{
+ /* Initialize legacy hair too, to avoid verbosity in callers. */
+ DRW_hair_init();
+
+#if defined(USE_TRANSFORM_FEEDBACK) || defined(USE_COMPUTE_SHADERS)
+ g_tf_pass = DRW_pass_create("Update Curves Pass", (DRWState)0);
+#else
+ g_tf_pass = DRW_pass_create("Update Curves Pass", DRW_STATE_WRITE_COLOR);
+#endif
+
+ if (g_dummy_vbo == nullptr) {
+ /* initialize vertex format */
+ GPUVertFormat format = {0};
+ uint dummy_id = GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ g_dummy_vbo = GPU_vertbuf_create_with_format(&format);
+
+ const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_vertbuf_data_alloc(g_dummy_vbo, 1);
+ GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert);
+ /* Create vbo immediately to bind to texture buffer. */
+ GPU_vertbuf_use(g_dummy_vbo);
+
+ g_dummy_texture = GPU_texture_create_from_vertbuf("hair_dummy_attr", g_dummy_vbo);
+ }
+}
+
+static void drw_curves_cache_shgrp_attach_resources(DRWShadingGroup *shgrp,
+ CurvesEvalCache *cache,
+ const int subdiv)
+{
+ DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", cache->point_tex);
+ DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex);
+ DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
+ DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
+}
+
+static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int subdiv)
+{
+ const int strands_len = cache->strands_len;
+ const int final_points_len = cache->final[subdiv].strands_res * strands_len;
+ if (final_points_len > 0) {
+ GPUShader *shader = curves_eval_shader_get(CURVES_EVAL_CATMULL_ROM);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass);
+ drw_curves_cache_shgrp_attach_resources(shgrp, cache, subdiv);
+ DRW_shgroup_vertex_buffer(shgrp, "posTime", cache->final[subdiv].proc_buf);
+
+ const int max_strands_per_call = GPU_max_work_group_count(0);
+ int strands_start = 0;
+ while (strands_start < strands_len) {
+ int batch_strands_len = MIN2(strands_len - strands_start, max_strands_per_call);
+ DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start);
+ DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final[subdiv].strands_res, 1);
+ strands_start += batch_strands_len;
+ }
+ }
+}
+
+static void drw_curves_cache_update_transform_feedback(CurvesEvalCache *cache, const int subdiv)
+{
+ const int final_points_len = cache->final[subdiv].strands_res * cache->strands_len;
+ if (final_points_len > 0) {
+ GPUShader *tf_shader = curves_eval_shader_get(CURVES_EVAL_CATMULL_ROM);
+
+#ifdef USE_TRANSFORM_FEEDBACK
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
+ tf_shader, g_tf_pass, cache->final[subdiv].proc_buf);
+#else
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
+
+ CurvesEvalCall *pr_call = MEM_new<CurvesEvalCall>(__func__);
+ pr_call->next = g_tf_calls;
+ pr_call->vbo = cache->final[subdiv].proc_buf;
+ pr_call->shgrp = tf_shgrp;
+ pr_call->vert_len = final_points_len;
+ g_tf_calls = pr_call;
+ DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
+ DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
+#endif
+
+ drw_curves_cache_shgrp_attach_resources(tf_shgrp, cache, subdiv);
+ DRW_shgroup_call_procedural_points(tf_shgrp, nullptr, final_points_len);
+ }
+}
+
+static CurvesEvalCache *drw_curves_cache_get(Object *object,
+ GPUMaterial *gpu_material,
+ int subdiv,
+ int thickness_res)
+{
+ CurvesEvalCache *cache;
+ bool update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res);
+
+ if (update) {
+ if (drw_curves_shader_type_get() == PART_REFINE_SHADER_COMPUTE) {
+ drw_curves_cache_update_compute(cache, subdiv);
+ }
+ else {
+ drw_curves_cache_update_transform_feedback(cache, subdiv);
+ }
+ }
+ return cache;
+}
+
+GPUVertBuf *DRW_curves_pos_buffer_get(Object *object)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ int subdiv = scene->r.hair_subdiv;
+ int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
+
+ CurvesEvalCache *cache = drw_curves_cache_get(object, nullptr, subdiv, thickness_res);
+
+ return cache->final[subdiv].proc_buf;
+}
+
+DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
+ DRWShadingGroup *shgrp_parent,
+ GPUMaterial *gpu_material)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ int subdiv = scene->r.hair_subdiv;
+ int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
+
+ CurvesEvalCache *curves_cache = drw_curves_cache_get(
+ object, gpu_material, subdiv, thickness_res);
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
+
+ /* Fix issue with certain driver not drawing anything if there is no texture bound to
+ * "ac", "au", "u" or "c". */
+ DRW_shgroup_uniform_texture(shgrp, "u", g_dummy_texture);
+ DRW_shgroup_uniform_texture(shgrp, "au", g_dummy_texture);
+ DRW_shgroup_uniform_texture(shgrp, "c", g_dummy_texture);
+ DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
+
+ /* TODO: Generalize radius implementation for curves data type. */
+ float hair_rad_shape = 1.0f;
+ float hair_rad_root = 0.005f;
+ float hair_rad_tip = 0.0f;
+ bool hair_close_tip = true;
+
+ DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_tex);
+ if (curves_cache->length_tex) {
+ DRW_shgroup_uniform_texture(shgrp, "hairLen", curves_cache->length_tex);
+ }
+ DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].strands_res, 1);
+ DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
+ DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->obmat);
+ 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 curves and render with orco, bypass
+ * culling test. */
+ GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
+ DRW_shgroup_call_no_cull(shgrp, geom, object);
+
+ return shgrp;
+}
+
+void DRW_curves_update()
+{
+ /* Update legacy hair too, to avoid verbosity in callers. */
+ DRW_hair_update();
+
+#ifndef USE_TRANSFORM_FEEDBACK
+ /**
+ * Workaround to transform feedback not working on mac.
+ * On some system it crashes (see T58489) and on some other it renders garbage (see T60171).
+ *
+ * So instead of using transform feedback we render to a texture,
+ * read back the result to system memory and re-upload as VBO data.
+ * It is really not ideal performance wise, but it is the simplest
+ * and the most local workaround that still uses the power of the GPU.
+ */
+
+ if (g_tf_calls == nullptr) {
+ return;
+ }
+
+ /* Search ideal buffer size. */
+ uint max_size = 0;
+ for (CurvesEvalCall *pr_call = g_tf_calls; pr_call; pr_call = pr_call->next) {
+ max_size = max_ii(max_size, pr_call->vert_len);
+ }
+
+ /* Create target Texture / Frame-buffer */
+ /* Don't use max size as it can be really heavy and fail.
+ * Do chunks of maximum 2048 * 2048 hair points. */
+ int width = 2048;
+ int height = min_ii(width, 1 + max_size / width);
+ GPUTexture *tex = DRW_texture_pool_query_2d(
+ width, height, GPU_RGBA32F, (DrawEngineType *)DRW_curves_update);
+ g_tf_target_height = height;
+ g_tf_target_width = width;
+
+ GPUFrameBuffer *fb = nullptr;
+ GPU_framebuffer_ensure_config(&fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(tex),
+ });
+
+ float *data = static_cast<float *>(
+ MEM_mallocN(sizeof(float[4]) * width * height, "tf fallback buffer"));
+
+ GPU_framebuffer_bind(fb);
+ while (g_tf_calls != nullptr) {
+ CurvesEvalCall *pr_call = g_tf_calls;
+ g_tf_calls = g_tf_calls->next;
+
+ g_tf_id_offset = 0;
+ while (pr_call->vert_len > 0) {
+ int max_read_px_len = min_ii(width * height, pr_call->vert_len);
+
+ DRW_draw_pass_subset(g_tf_pass, pr_call->shgrp, pr_call->shgrp);
+ /* Read back result to main memory. */
+ GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, GPU_DATA_FLOAT, data);
+ /* Upload back to VBO. */
+ GPU_vertbuf_use(pr_call->vbo);
+ GPU_vertbuf_update_sub(pr_call->vbo,
+ sizeof(float[4]) * g_tf_id_offset,
+ sizeof(float[4]) * max_read_px_len,
+ data);
+
+ g_tf_id_offset += max_read_px_len;
+ pr_call->vert_len -= max_read_px_len;
+ }
+
+ MEM_freeN(pr_call);
+ }
+
+ MEM_freeN(data);
+ GPU_framebuffer_free(fb);
+#else
+ /* Just render the pass when using compute shaders or transform feedback. */
+ DRW_draw_pass(g_tf_pass);
+ if (drw_curves_shader_type_get() == PART_REFINE_SHADER_COMPUTE) {
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
+ }
+#endif
+}
+
+void DRW_curves_free()
+{
+ DRW_hair_free();
+
+ GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo);
+ DRW_TEXTURE_FREE_SAFE(g_dummy_texture);
+}
diff --git a/source/blender/draw/intern/draw_curves_private.h b/source/blender/draw/intern/draw_curves_private.h
new file mode 100644
index 00000000000..76d5f15319d
--- /dev/null
+++ b/source/blender/draw/intern/draw_curves_private.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2017 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup draw
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_THICKRES 2 /* see eHairType */
+#define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */
+
+typedef enum CurvesEvalShader {
+ CURVES_EVAL_CATMULL_ROM = 0,
+ CURVES_EVAL_BEZIER = 1,
+} CurvesEvalShader;
+#define CURVES_EVAL_SHADER_NUM 3
+
+struct GPUVertBuf;
+struct GPUIndexBuf;
+struct GPUBatch;
+struct GPUTexture;
+
+typedef struct CurvesEvalFinalCache {
+ /* Output of the subdivision stage: vertex buffer sized to subdiv level. */
+ GPUVertBuf *proc_buf;
+ GPUTexture *proc_tex;
+
+ /* Just contains a huge index buffer used to draw the final curves. */
+ GPUBatch *proc_hairs[MAX_THICKRES];
+
+ /* Points per curve, at least 2. */
+ int strands_res;
+} CurvesEvalFinalCache;
+
+/* Curves procedural display: Evaluation is done on the GPU. */
+typedef struct CurvesEvalCache {
+ /* Input control points */
+ GPUVertBuf *proc_point_buf;
+ GPUTexture *point_tex;
+
+ /** Info of control points strands (segment count and base index) */
+ GPUVertBuf *proc_strand_buf;
+ GPUTexture *strand_tex;
+
+ /* Curve length data. */
+ GPUVertBuf *proc_length_buf;
+ GPUTexture *length_tex;
+
+ GPUVertBuf *proc_strand_seg_buf;
+ GPUTexture *strand_seg_tex;
+
+ CurvesEvalFinalCache final[MAX_HAIR_SUBDIV];
+
+ int strands_len;
+ int elems_len;
+ int point_len;
+} CurvesEvalCache;
+
+/**
+ * Ensure all textures and buffers needed for GPU accelerated drawing.
+ */
+bool curves_ensure_procedural_data(struct Object *object,
+ struct CurvesEvalCache **r_hair_cache,
+ struct GPUMaterial *gpu_material,
+ int subdiv,
+ int thickness_res);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c
index 667bd24dddb..d3d4bbf505e 100644
--- a/source/blender/draw/intern/draw_fluid.c
+++ b/source/blender/draw/intern/draw_fluid.c
@@ -9,6 +9,7 @@
#include <string.h>
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -21,6 +22,8 @@
#include "GPU_texture.h"
+#include "draw_manager.h"
+
#include "draw_common.h" /* Own include. */
#ifdef WITH_FLUID
@@ -419,46 +422,6 @@ static bool get_smoke_velocity_field(FluidDomainSettings *fds,
/** \name Public API
* \{ */
-void DRW_smoke_free(FluidModifierData *fmd)
-{
- if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
- if (fmd->domain->tex_density) {
- GPU_texture_free(fmd->domain->tex_density);
- fmd->domain->tex_density = NULL;
- }
-
- if (fmd->domain->tex_color) {
- GPU_texture_free(fmd->domain->tex_color);
- fmd->domain->tex_color = NULL;
- }
-
- if (fmd->domain->tex_shadow) {
- GPU_texture_free(fmd->domain->tex_shadow);
- fmd->domain->tex_shadow = NULL;
- }
-
- if (fmd->domain->tex_flame) {
- GPU_texture_free(fmd->domain->tex_flame);
- fmd->domain->tex_flame = NULL;
- }
-
- if (fmd->domain->tex_flame_coba) {
- GPU_texture_free(fmd->domain->tex_flame_coba);
- fmd->domain->tex_flame_coba = NULL;
- }
-
- if (fmd->domain->tex_coba) {
- GPU_texture_free(fmd->domain->tex_coba);
- fmd->domain->tex_coba = NULL;
- }
-
- if (fmd->domain->tex_field) {
- GPU_texture_free(fmd->domain->tex_field);
- fmd->domain->tex_field = NULL;
- }
- }
-}
-
void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
{
#ifndef WITH_FLUID
@@ -469,6 +432,7 @@ void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
if (!fds->tex_field) {
fds->tex_field = create_field_texture(fds, false);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_field));
}
if (!fds->tex_coba && !ELEM(fds->coba_field,
FLUID_DOMAIN_FIELD_PHI,
@@ -478,6 +442,7 @@ void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
FLUID_DOMAIN_FIELD_FLAGS,
FLUID_DOMAIN_FIELD_PRESSURE)) {
fds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, fds->coba);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_coba));
}
}
#endif
@@ -493,19 +458,24 @@ void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
if (!fds->tex_density) {
fds->tex_density = create_density_texture(fds, highres);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_density));
}
if (!fds->tex_color) {
fds->tex_color = create_color_texture(fds, highres);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_color));
}
if (!fds->tex_flame) {
fds->tex_flame = create_flame_texture(fds, highres);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_flame));
}
if (!fds->tex_flame_coba && fds->tex_flame) {
fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_flame_coba));
}
if (!fds->tex_shadow) {
fds->tex_shadow = create_volume_texture(
fds->res, GPU_R8, GPU_DATA_FLOAT, manta_smoke_get_shadow(fds->fluid));
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_shadow));
}
}
#endif /* WITH_FLUID */
@@ -536,6 +506,9 @@ void DRW_smoke_ensure_velocity(FluidModifierData *fmd)
"vely", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_y);
fds->tex_velocity_z = GPU_texture_create_3d(
"velz", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_z);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_x));
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_y));
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_z));
}
}
#endif /* WITH_FLUID */
@@ -551,6 +524,7 @@ void DRW_fluid_ensure_flags(FluidModifierData *fmd)
if (!fds->tex_flags) {
fds->tex_flags = create_volume_texture(
fds->res, GPU_R8UI, GPU_DATA_INT, manta_smoke_get_flags(fds->fluid));
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_flags));
swizzle_texture_channel_single(fds->tex_flags);
}
@@ -568,42 +542,29 @@ void DRW_fluid_ensure_range_field(FluidModifierData *fmd)
if (!fds->tex_range_field) {
fds->tex_range_field = create_field_texture(fds, true);
+ BLI_addtail(&DST.vmempool->smoke_textures, BLI_genericNodeN(&fds->tex_range_field));
}
}
#endif /* WITH_FLUID */
}
-void DRW_smoke_free_velocity(FluidModifierData *fmd)
+void DRW_smoke_init(DRWData *drw_data)
{
- /* TODO: Unify with the other #GPU_free_smoke. */
-
- if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
- if (fmd->domain->tex_velocity_x) {
- GPU_texture_free(fmd->domain->tex_velocity_x);
- }
-
- if (fmd->domain->tex_velocity_y) {
- GPU_texture_free(fmd->domain->tex_velocity_y);
- }
-
- if (fmd->domain->tex_velocity_z) {
- GPU_texture_free(fmd->domain->tex_velocity_z);
- }
-
- if (fmd->domain->tex_flags) {
- GPU_texture_free(fmd->domain->tex_flags);
- }
-
- if (fmd->domain->tex_range_field) {
- GPU_texture_free(fmd->domain->tex_range_field);
- }
+ BLI_listbase_clear(&drw_data->smoke_textures);
+}
- fmd->domain->tex_velocity_x = NULL;
- fmd->domain->tex_velocity_y = NULL;
- fmd->domain->tex_velocity_z = NULL;
- fmd->domain->tex_flags = NULL;
- fmd->domain->tex_range_field = NULL;
+void DRW_smoke_exit(DRWData *drw_data)
+{
+ /* Free Smoke Textures after rendering */
+ /* XXX This is a waste of processing and GPU bandwidth if nothing
+ * is updated. But the problem is since Textures are stored in the
+ * modifier we don't want them to take precious VRAM if the
+ * modifier is not used for display. We should share them for
+ * all viewport in a redraw at least. */
+ LISTBASE_FOREACH (LinkData *, link, &drw_data->smoke_textures) {
+ GPU_TEXTURE_FREE_SAFE(*(GPUTexture **)link->data);
}
+ BLI_freelistN(&drw_data->smoke_textures);
}
/** \} */
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index aac6f7e58c5..8351452769d 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -179,25 +179,6 @@ static ParticleHairCache *drw_hair_particle_cache_get(Object *object,
return cache;
}
-static ParticleHairCache *drw_curves_cache_get(Object *object,
- GPUMaterial *gpu_material,
- int subdiv,
- int thickness_res)
-{
- ParticleHairCache *cache;
- bool update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res);
-
- if (update) {
- if (drw_hair_shader_type_get() == PART_REFINE_SHADER_COMPUTE) {
- drw_hair_particle_cache_update_compute(cache, subdiv);
- }
- else {
- drw_hair_particle_cache_update_transform_feedback(cache, subdiv);
- }
- }
- return cache;
-}
-
GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -212,19 +193,6 @@ GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, Modifi
return cache->final[subdiv].proc_buf;
}
-GPUVertBuf *DRW_curves_pos_buffer_get(Object *object)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
-
- int subdiv = scene->r.hair_subdiv;
- int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
-
- ParticleHairCache *cache = drw_curves_cache_get(object, NULL, subdiv, thickness_res);
-
- return cache->final[subdiv].proc_buf;
-}
-
void DRW_hair_duplimat_get(Object *object,
ParticleSystem *UNUSED(psys),
ModifierData *UNUSED(md),
@@ -323,71 +291,6 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
return shgrp;
}
-DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
- DRWShadingGroup *shgrp_parent,
- GPUMaterial *gpu_material)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
-
- int subdiv = scene->r.hair_subdiv;
- int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
-
- ParticleHairCache *curves_cache = drw_curves_cache_get(
- object, gpu_material, subdiv, thickness_res);
-
- DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
-
- /* TODO: optimize this. Only bind the ones GPUMaterial needs. */
- for (int i = 0; i < curves_cache->num_uv_layers; i++) {
- for (int n = 0; n < MAX_LAYER_NAME_CT && curves_cache->uv_layer_names[i][n][0] != '\0'; n++) {
- DRW_shgroup_uniform_texture(
- shgrp, curves_cache->uv_layer_names[i][n], curves_cache->uv_tex[i]);
- }
- }
- for (int i = 0; i < curves_cache->num_col_layers; i++) {
- for (int n = 0; n < MAX_LAYER_NAME_CT && curves_cache->col_layer_names[i][n][0] != '\0'; n++) {
- DRW_shgroup_uniform_texture(
- shgrp, curves_cache->col_layer_names[i][n], curves_cache->col_tex[i]);
- }
- }
-
- /* Fix issue with certain driver not drawing anything if there is no texture bound to
- * "ac", "au", "u" or "c". */
- if (curves_cache->num_uv_layers == 0) {
- DRW_shgroup_uniform_texture(shgrp, "u", g_dummy_texture);
- DRW_shgroup_uniform_texture(shgrp, "au", g_dummy_texture);
- }
- if (curves_cache->num_col_layers == 0) {
- DRW_shgroup_uniform_texture(shgrp, "c", g_dummy_texture);
- DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
- }
-
- /* TODO: Generalize radius implementation for curves data type. */
- float hair_rad_shape = 1.0f;
- float hair_rad_root = 0.005f;
- float hair_rad_tip = 0.0f;
- bool hair_close_tip = true;
-
- DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_tex);
- if (curves_cache->length_tex) {
- DRW_shgroup_uniform_texture(shgrp, "hairLen", curves_cache->length_tex);
- }
- DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].strands_res, 1);
- DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
- DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
- DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->obmat);
- 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 curves and render with orco, bypass
- * culling test. */
- GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
- DRW_shgroup_call_no_cull(shgrp, geom, object);
-
- return shgrp;
-}
-
void DRW_hair_update(void)
{
#ifndef USE_TRANSFORM_FEEDBACK
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index 58e8609106b..5d84c8863f2 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -75,8 +75,6 @@ typedef struct ParticleHairCache {
int point_len;
} ParticleHairCache;
-void particle_batch_cache_clear_hair(struct ParticleHairCache *hair_cache);
-
/**
* Ensure all textures and buffers needed for GPU accelerated drawing.
*/
@@ -88,15 +86,6 @@ bool particles_ensure_procedural_data(struct Object *object,
int subdiv,
int thickness_res);
-/**
- * Ensure all textures and buffers needed for GPU accelerated drawing.
- */
-bool curves_ensure_procedural_data(struct Object *object,
- struct ParticleHairCache **r_hair_cache,
- struct GPUMaterial *gpu_material,
- int subdiv,
- int thickness_res);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 88d05fcd928..adf9d4a13df 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -478,6 +478,7 @@ void DRW_viewport_data_free(DRWData *drw_data)
MEM_freeN(drw_data->matrices_ubo);
MEM_freeN(drw_data->obinfos_ubo);
}
+ DRW_volume_ubos_pool_free(drw_data->volume_grids_ubos);
MEM_freeN(drw_data);
}
@@ -1649,7 +1650,9 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_globals_update();
drw_debug_init();
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
/* No frame-buffer allowed before drawing. */
BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get());
@@ -1704,7 +1707,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
GPU_framebuffer_bind(DST.default_framebuffer);
GPU_framebuffer_clear_depth_stencil(DST.default_framebuffer, 1.0f, 0xFF);
- DRW_hair_update();
+ DRW_curves_update();
DRW_draw_callbacks_pre_scene();
@@ -1715,6 +1718,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
GPU_flush();
}
+ DRW_smoke_exit(DST.vmempool);
+
DRW_stats_reset();
DRW_draw_callbacks_post_scene();
@@ -1999,6 +2004,8 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
GPU_framebuffer_restore();
+ DRW_smoke_exit(DST.vmempool);
+
drw_manager_exit(&DST);
/* Reset state after drawing */
@@ -2015,7 +2022,9 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
drw_task_graph_init();
const int object_type_exclude_viewport = draw_ctx->v3d ?
@@ -2070,7 +2079,9 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
drw_manager_init(&DST, NULL, NULL);
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
ViewportEngineData *data = DRW_view_data_engine_data_get_ensure(DST.view_data_active,
draw_engine_type);
@@ -2079,6 +2090,8 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
callback(data, user_data);
DST.buffer_finish_called = false;
+ DRW_smoke_exit(DST.vmempool);
+
GPU_framebuffer_restore();
/* The use of custom pipeline in other thread using the same
@@ -2095,11 +2108,15 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
void DRW_cache_restart(void)
{
+ DRW_smoke_exit(DST.vmempool);
+
drw_manager_init(&DST, DST.viewport, (int[2]){UNPACK2(DST.size)});
DST.buffer_finish_called = false;
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
}
void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
@@ -2416,7 +2433,9 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
/* Init engines */
drw_engines_init();
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
{
drw_engines_cache_init();
@@ -2493,7 +2512,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DRW_state_reset();
DRW_draw_callbacks_pre_scene();
- DRW_hair_update();
+ DRW_curves_update();
/* Only 1-2 passes. */
while (true) {
@@ -2511,6 +2530,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
}
+ DRW_smoke_exit(DST.vmempool);
+
DRW_state_reset();
drw_engines_disable();
@@ -2586,7 +2607,9 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph,
/* Init engines */
drw_engines_init();
- DRW_hair_init();
+ DRW_curves_init();
+ DRW_volume_init(DST.vmempool);
+ DRW_smoke_init(DST.vmempool);
{
drw_engines_cache_init();
@@ -2619,10 +2642,12 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph,
/* Start Drawing */
DRW_state_reset();
- DRW_hair_update();
+ DRW_curves_update();
drw_engines_draw_scene();
+ DRW_smoke_exit(DST.vmempool);
+
DRW_state_reset();
/* TODO: Reading depth for operators should be done here. */
@@ -3008,7 +3033,8 @@ void DRW_engines_free(void)
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
DRW_shaders_free();
- DRW_hair_free();
+ DRW_curves_free();
+ DRW_volume_free();
DRW_shape_cache_free();
DRW_stats_free();
DRW_globals_free();
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index 832897b7040..8812f112014 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -527,6 +527,10 @@ typedef struct DRWData {
struct GPUUniformBuf **obinfos_ubo;
struct GHash *obattrs_ubo_pool;
uint ubo_len;
+ /** Per draw-call volume object data. */
+ void *volume_grids_ubos; /* VolumeUniformBufPool */
+ /** List of smoke textures to free after drawing. */
+ ListBase smoke_textures;
/** Texture pool to reuse temp texture across engines. */
/* TODO(@fclem): The pool could be shared even between view-ports. */
struct DRWTexturePool *texture_pool;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 39f083aaf96..b5432da0957 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -15,6 +15,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
+#include "BKE_volume.h"
#include "DNA_curve_types.h"
#include "DNA_mesh_types.h"
@@ -555,10 +556,19 @@ void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup,
static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4])
{
ID *ob_data = (ob) ? ob->data : NULL;
+ float loc[3], size[3];
float *texcoloc = NULL;
float *texcosize = NULL;
if (ob_data != NULL) {
switch (GS(ob_data->name)) {
+ case ID_VO: {
+ BoundBox *bbox = BKE_volume_boundbox_get(ob);
+ mid_v3_v3v3(loc, bbox->vec[0], bbox->vec[6]);
+ sub_v3_v3v3(size, bbox->vec[0], bbox->vec[6]);
+ texcoloc = loc;
+ texcosize = size;
+ break;
+ }
case ID_ME:
BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, &texcosize);
break;
diff --git a/source/blender/draw/intern/draw_shader.c b/source/blender/draw/intern/draw_shader.c
index 53da300c106..487a09d313d 100644
--- a/source/blender/draw/intern/draw_shader.c
+++ b/source/blender/draw/intern/draw_shader.c
@@ -92,6 +92,30 @@ GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
return e_data.hair_refine_sh[refinement];
}
+GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type, eParticleRefineShaderType sh_type)
+{
+ /* TODO: Implement curves evaluation types (Bezier and Catmull Rom). */
+ if (e_data.hair_refine_sh[type] == NULL) {
+ GPUShader *sh = NULL;
+ switch (sh_type) {
+ case PART_REFINE_SHADER_COMPUTE:
+ sh = hair_refine_shader_compute_create(type);
+ break;
+ case PART_REFINE_SHADER_TRANSFORM_FEEDBACK:
+ sh = hair_refine_shader_transform_feedback_create(type);
+ break;
+ case PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND:
+ sh = hair_refine_shader_transform_feedback_workaround_create(type);
+ break;
+ default:
+ BLI_assert_msg(0, "Incorrect shader type");
+ }
+ e_data.hair_refine_sh[type] = sh;
+ }
+
+ return e_data.hair_refine_sh[type];
+}
+
/** \} */
void DRW_shaders_free(void)
diff --git a/source/blender/draw/intern/draw_shader.h b/source/blender/draw/intern/draw_shader.h
index 65b9cafc1d9..650e78c9362 100644
--- a/source/blender/draw/intern/draw_shader.h
+++ b/source/blender/draw/intern/draw_shader.h
@@ -7,6 +7,7 @@
#pragma once
+#include "draw_curves_private.h"
#include "draw_hair_private.h"
#ifdef __cplusplus
@@ -25,6 +26,10 @@ typedef enum eParticleRefineShaderType {
struct GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
eParticleRefineShaderType sh_type);
+
+struct GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type,
+ eParticleRefineShaderType sh_type);
+
void DRW_shaders_free(void);
#ifdef __cplusplus
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 58875c0496a..db128fffde7 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -6,12 +6,16 @@
typedef struct ViewInfos ViewInfos;
typedef struct ObjectMatrices ObjectMatrices;
typedef struct ObjectInfos ObjectInfos;
+typedef struct VolumeInfos VolumeInfos;
#endif
#define DRW_SHADER_SHARED_H
#define DRW_RESOURCE_CHUNK_LEN 512
+/* Define the maximum number of grid we allow in a volume UBO. */
+#define DRW_GRID_PER_VOLUME_MAX 16
+
struct ViewInfos {
/* View matrices */
float4x4 persmat;
@@ -63,6 +67,18 @@ struct ObjectInfos {
};
BLI_STATIC_ASSERT_ALIGN(ViewInfos, 16)
+struct VolumeInfos {
+ /* Object to grid-space. */
+ float4x4 grids_xform[DRW_GRID_PER_VOLUME_MAX];
+ /* NOTE: vec4 for alignment. Only float3 needed. */
+ float4 color_mul;
+ float density_scale;
+ float temperature_mul;
+ float temperature_bias;
+ float _pad;
+};
+BLI_STATIC_ASSERT_ALIGN(VolumeInfos, 16)
+
#define OrcoTexCoFactors (drw_infos[resource_id].drw_OrcoTexCoFactors)
#define ObjectInfo (drw_infos[resource_id].drw_Infos)
#define ObjectColor (drw_infos[resource_id].drw_ObjectColor)
diff --git a/source/blender/draw/intern/draw_volume.cc b/source/blender/draw/intern/draw_volume.cc
new file mode 100644
index 00000000000..8d9a6f486e2
--- /dev/null
+++ b/source/blender/draw/intern/draw_volume.cc
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup draw
+ *
+ * \brief Contains Volume object GPU attributes configuration.
+ */
+
+#include "DRW_gpu_wrapper.hh"
+#include "DRW_render.h"
+
+#include "DNA_fluid_types.h"
+#include "DNA_volume_types.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 "GPU_material.h"
+
+#include "draw_common.h"
+#include "draw_manager.h"
+
+using namespace blender;
+using namespace blender::draw;
+using VolumeInfosBuf = blender::draw::UniformBuffer<VolumeInfos>;
+
+static struct {
+ GPUTexture *dummy_zero;
+ GPUTexture *dummy_one;
+ float dummy_grid_mat[4][4];
+} g_data = {};
+
+struct VolumeUniformBufPool {
+ Vector<VolumeInfosBuf *> ubos;
+ uint used = 0;
+
+ ~VolumeUniformBufPool()
+ {
+ for (VolumeInfosBuf *ubo : ubos) {
+ delete ubo;
+ }
+ }
+
+ void reset()
+ {
+ used = 0;
+ }
+
+ VolumeInfosBuf *alloc()
+ {
+ if (used >= ubos.size()) {
+ VolumeInfosBuf *buf = new VolumeInfosBuf();
+ ubos.append(buf);
+ return buf;
+ }
+ return ubos[used++];
+ }
+};
+
+void DRW_volume_ubos_pool_free(void *pool)
+{
+ delete reinterpret_cast<VolumeUniformBufPool *>(pool);
+}
+
+static void drw_volume_globals_init()
+{
+ const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ g_data.dummy_zero = GPU_texture_create_3d(
+ "dummy_zero", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, zero);
+ g_data.dummy_one = GPU_texture_create_3d(
+ "dummy_one", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, one);
+ GPU_texture_wrap_mode(g_data.dummy_zero, true, true);
+ GPU_texture_wrap_mode(g_data.dummy_one, true, true);
+
+ memset(g_data.dummy_grid_mat, 0, sizeof(g_data.dummy_grid_mat));
+}
+
+void DRW_volume_free(void)
+{
+ GPU_TEXTURE_FREE_SAFE(g_data.dummy_zero);
+ GPU_TEXTURE_FREE_SAFE(g_data.dummy_one);
+}
+
+static GPUTexture *grid_default_texture(eGPUDefaultValue default_value)
+{
+ switch (default_value) {
+ case GPU_DEFAULT_0:
+ return g_data.dummy_zero;
+ case GPU_DEFAULT_1:
+ return g_data.dummy_one;
+ }
+ return g_data.dummy_zero;
+}
+
+void DRW_volume_init(DRWData *drw_data)
+{
+ if (drw_data->volume_grids_ubos == nullptr) {
+ drw_data->volume_grids_ubos = new VolumeUniformBufPool();
+ }
+ VolumeUniformBufPool *pool = (VolumeUniformBufPool *)drw_data->volume_grids_ubos;
+ pool->reset();
+
+ if (g_data.dummy_one == nullptr) {
+ drw_volume_globals_init();
+ }
+}
+
+static DRWShadingGroup *drw_volume_object_grids_init(Object *ob,
+ ListBase *attrs,
+ DRWShadingGroup *grp)
+{
+ VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos;
+ VolumeInfosBuf &volume_infos = *pool->alloc();
+
+ Volume *volume = (Volume *)ob->data;
+ BKE_volume_load(volume, G.main);
+
+ grp = DRW_shgroup_create_sub(grp);
+
+ volume_infos.density_scale = BKE_volume_density_scale(volume, ob->obmat);
+ volume_infos.color_mul = float4(1.0f);
+ volume_infos.temperature_mul = 1.0f;
+ volume_infos.temperature_bias = 0.0f;
+
+ /* Bind volume grid textures. */
+ int grid_id = 0;
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
+ const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, attr->name);
+ const DRWVolumeGrid *drw_grid = (volume_grid) ?
+ DRW_volume_batch_cache_get_grid(volume, volume_grid) :
+ nullptr;
+
+ /* Handle 3 cases here:
+ * - Grid exists and texture was loaded -> use texture.
+ * - Grid exists but has zero size or failed to load -> use zero.
+ * - Grid does not exist -> use default value. */
+ const GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture :
+ (volume_grid) ? g_data.dummy_zero :
+ grid_default_texture(attr->default_value);
+ DRW_shgroup_uniform_texture(grp, attr->input_name, grid_tex);
+
+ copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), drw_grid->object_to_texture);
+ }
+
+ volume_infos.push_update();
+
+ DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos);
+
+ return grp;
+}
+
+static DRWShadingGroup *drw_volume_object_mesh_init(Scene *scene,
+ Object *ob,
+ ListBase *attrs,
+ DRWShadingGroup *grp)
+{
+ VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos;
+ VolumeInfosBuf &volume_infos = *pool->alloc();
+
+ ModifierData *md = nullptr;
+
+ volume_infos.density_scale = 1.0f;
+ volume_infos.color_mul = float4(1.0f);
+ volume_infos.temperature_mul = 1.0f;
+ volume_infos.temperature_bias = 0.0f;
+
+ /* Smoke Simulation */
+ if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) &&
+ (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) &&
+ ((FluidModifierData *)md)->domain != nullptr) {
+ FluidModifierData *fmd = (FluidModifierData *)md;
+ FluidDomainSettings *fds = fmd->domain;
+
+ /* Don't try to show liquid domains here. */
+ if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) {
+ return nullptr;
+ }
+
+ if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS)) {
+ DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE);
+ }
+
+ grp = DRW_shgroup_create_sub(grp);
+
+ int grid_id = 0;
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
+ if (STREQ(attr->name, "density")) {
+ DRW_shgroup_uniform_texture_ref(
+ grp, attr->input_name, fds->tex_density ? &fds->tex_density : &g_data.dummy_one);
+ }
+ else if (STREQ(attr->name, "color")) {
+ DRW_shgroup_uniform_texture_ref(
+ grp, attr->input_name, fds->tex_color ? &fds->tex_color : &g_data.dummy_one);
+ }
+ else if (STR_ELEM(attr->name, "flame", "temperature")) {
+ DRW_shgroup_uniform_texture_ref(
+ grp, attr->input_name, fds->tex_flame ? &fds->tex_flame : &g_data.dummy_zero);
+ }
+ else {
+ DRW_shgroup_uniform_texture(
+ grp, attr->input_name, grid_default_texture(attr->default_value));
+ }
+ copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat);
+ }
+
+ bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
+ (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0);
+ if (use_constant_color) {
+ volume_infos.color_mul = float4(UNPACK3(fds->active_color), 1.0f);
+ }
+
+ /* Output is such that 0..1 maps to 0..1000K */
+ volume_infos.temperature_mul = fds->flame_max_temp - fds->flame_ignition;
+ volume_infos.temperature_bias = fds->flame_ignition;
+ }
+ else {
+ grp = DRW_shgroup_create_sub(grp);
+
+ int grid_id = 0;
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
+ DRW_shgroup_uniform_texture(
+ grp, attr->input_name, grid_default_texture(attr->default_value));
+ copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat);
+ }
+ }
+
+ volume_infos.push_update();
+
+ DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos);
+
+ return grp;
+}
+
+static DRWShadingGroup *drw_volume_world_grids_init(ListBase *attrs, DRWShadingGroup *grp)
+{
+ /* Bind default volume grid textures. */
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
+ DRW_shgroup_uniform_texture(grp, attr->input_name, grid_default_texture(attr->default_value));
+ }
+ return grp;
+}
+
+DRWShadingGroup *DRW_shgroup_volume_create_sub(Scene *scene,
+ Object *ob,
+ DRWShadingGroup *shgrp,
+ GPUMaterial *gpu_material)
+{
+ ListBase attrs = GPU_material_attributes(gpu_material);
+
+ if (ob == nullptr) {
+ return drw_volume_world_grids_init(&attrs, shgrp);
+ }
+ if (ob->type == OB_VOLUME) {
+ return drw_volume_object_grids_init(ob, &attrs, shgrp);
+ }
+ return drw_volume_object_mesh_init(scene, ob, &attrs, shgrp);
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
index d52226a4c90..4cb68cad66c 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
@@ -173,7 +173,7 @@ static void extract_vcol_init(const MeshRenderData *mr,
}
BMIter iter;
- const bool is_byte = ref.layer->type == CD_MLOOPCOL;
+ const bool is_byte = ref.layer->type == CD_PROP_BYTE_COLOR;
const bool is_point = ref.domain == ATTR_DOMAIN_POINT;
BMFace *f;
@@ -318,7 +318,7 @@ static void extract_vcol_init_subdiv(const DRWSubdivCache *subdiv_cache,
BMIter iter;
BMFace *f;
int cd_ofs = cdata->layers[layer_i].offset;
- const bool is_byte = ref.layer->type == CD_MLOOPCOL;
+ const bool is_byte = ref.layer->type == CD_PROP_BYTE_COLOR;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMLoop *l_iter = f->l_first;
diff --git a/source/blender/draw/intern/shaders/common_attribute_lib.glsl b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
index 99db2929a13..30239a84c0c 100644
--- a/source/blender/draw/intern/shaders/common_attribute_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
@@ -19,3 +19,15 @@ vec4 attr_load_vec4(samplerBuffer attr);
vec3 attr_load_vec3(samplerBuffer attr);
vec2 attr_load_vec2(samplerBuffer attr);
float attr_load_float(samplerBuffer attr);
+
+vec3 attr_load_orco(sampler3D orco);
+vec4 attr_load_tangent(sampler3D tangent);
+vec3 attr_load_uv(sampler3D attr);
+vec4 attr_load_color(sampler3D tex);
+vec4 attr_load_vec4(sampler3D tex);
+vec3 attr_load_vec3(sampler3D tex);
+vec2 attr_load_vec2(sampler3D tex);
+float attr_load_float(sampler3D tex);
+
+float attr_load_temperature_post(float attr);
+vec4 attr_load_color_post(vec4 attr);
diff --git a/source/blender/draw/intern/shaders/draw_object_infos_info.hh b/source/blender/draw/intern/shaders/draw_object_infos_info.hh
index 392b016fc3b..c74a043ec97 100644
--- a/source/blender/draw/intern/shaders/draw_object_infos_info.hh
+++ b/source/blender/draw/intern/shaders/draw_object_infos_info.hh
@@ -6,3 +6,7 @@ GPU_SHADER_CREATE_INFO(draw_object_infos)
.typedef_source("draw_shader_shared.h")
.define("OBINFO_LIB")
.uniform_buf(1, "ObjectInfos", "drw_infos[DRW_RESOURCE_CHUNK_LEN]", Frequency::BATCH);
+
+GPU_SHADER_CREATE_INFO(draw_volume_infos)
+ .typedef_source("draw_shader_shared.h")
+ .uniform_buf(2, "VolumeInfos", "drw_volume", Frequency::BATCH);