diff options
Diffstat (limited to 'source/blender/draw/engines')
17 files changed, 466 insertions, 100 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a886fa26589..70933e21719 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -127,6 +127,12 @@ void EEVEE_cache_populate(void *vedata, Object *ob) if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } + else if (ob->type == OB_HAIR) { + EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + } + else if (ob->type == OB_VOLUME) { + EEVEE_volumes_cache_object_add(sldata, vedata, draw_ctx->scene, ob); + } else if (!USE_SCENE_LIGHT(draw_ctx->v3d)) { /* do not add any scene light sources to the cache */ } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 230a0725493..bb64fe32bc3 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -32,9 +32,10 @@ #include "BKE_paint.h" #include "BKE_particle.h" -#include "DNA_world_types.h" +#include "DNA_hair_types.h" #include "DNA_modifier_types.h" #include "DNA_view3d_types.h" +#include "DNA_world_types.h" #include "GPU_material.h" @@ -1021,7 +1022,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa EEVEE_PassList *psl = vedata->psl; - BLI_assert(!is_hair || (ob && psys && md)); + BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR))); SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR); SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); @@ -1715,7 +1716,12 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot) { Material *ma = BKE_object_material_get(ob, slot + 1); if (ma == NULL) { - ma = BKE_material_default_empty(); + if (ob->type == OB_VOLUME) { + ma = BKE_material_default_volume(); + } + else { + ma = BKE_material_default_empty(); + } } return ma; } @@ -2064,6 +2070,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, } } +void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow) +{ + eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, HAIR_MATERIAL_NR, cast_shadow); +} + void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 52fb8b3cced..e2470b4fa76 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -902,6 +902,10 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow); +void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow); void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index eedc64f32e6..c8357b56b18 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -177,7 +177,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *engine, - struct Depsgraph *UNUSED(depsgraph)) + struct Depsgraph *depsgraph) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); EEVEE_LightProbesInfo *pinfo = sldata->probes; @@ -211,6 +211,13 @@ void EEVEE_render_cache(void *vedata, if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } + else if (ob->type == OB_HAIR) { + EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + } + else if (ob->type == OB_VOLUME) { + Scene *scene = DEG_get_evaluated_scene(depsgraph); + EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob); + } else if (ob->type == OB_LIGHTPROBE) { EEVEE_lightprobes_cache_add(sldata, vedata, ob); } diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 41f8dddf0fb..0e82ac237c0 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -29,11 +29,15 @@ #include "DNA_object_force_types.h" #include "DNA_fluid_types.h" +#include "DNA_volume_types.h" #include "DNA_world_types.h" -#include "BKE_modifier.h" -#include "BKE_mesh.h" #include "BKE_fluid.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_volume.h" +#include "BKE_volume_render.h" #include "ED_screen.h" @@ -59,6 +63,7 @@ static struct { GPUTexture *depth_src; GPUTexture *dummy_density; + GPUTexture *dummy_color; GPUTexture *dummy_flame; GPUTexture *dummy_scatter; @@ -368,8 +373,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Fix principle volumetric not working with world materials. */ ListBase gpu_grids = GPU_material_volume_grids(mat); - for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; - gpu_grid = gpu_grid->next) { + LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) { DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density); } @@ -390,64 +394,92 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } -typedef struct EEVEE_InstanceVolumeMatrix { - DrawData dd; - float volume_mat[4][4]; -} EEVEE_InstanceVolumeMatrix; - -void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - Scene *scene, - Object *ob) +static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWShadingGroup *grp) { - static const float white[3] = {1.0f, 1.0f, 1.0f}; - - float *texcoloc = NULL; - float *texcosize = NULL; - struct ModifierData *md = NULL; - Material *ma = BKE_object_material_get(ob, 1); - - if (ma == NULL) { - return; + Volume *volume = ob->data; + BKE_volume_load(volume, G.main); + + /* Test if we need to use multiple transforms. */ + DRWVolumeGrid *first_drw_grid = NULL; + bool multiple_transforms = true; + + LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { + VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name); + DRWVolumeGrid *drw_grid = (volume_grid) ? + DRW_volume_batch_cache_get_grid(volume, volume_grid) : + NULL; + + if (drw_grid) { + if (first_drw_grid == NULL) { + first_drw_grid = drw_grid; + } + else if (drw_grid && + !equals_m4m4(drw_grid->object_to_texture, first_drw_grid->object_to_texture)) { + multiple_transforms = true; + break; + } + } } - float size[3]; - mat4_to_size(size, ob->obmat); - /* Check if any of the axes have 0 length. (see T69070) */ - const float epsilon = 1e-8f; - if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) { - return; + /* Bail out of no grids to render. */ + if (first_drw_grid == NULL) { + return false; } - struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); - eGPUMaterialStatus status = GPU_material_status(mat); - - if (status == GPU_MAT_QUEUED) { - vedata->stl->g_data->queued_shaders_count++; + /* Set transform matrix for the volume as a whole. This one is also used for + * clipping so must map the entire bounding box to 0..1. */ + float bounds_to_object[4][4]; + + if (multiple_transforms) { + /* For multiple grids with different transform, we first transform from object space + * to bounds, then for each individual grid from bounds to texture. */ + BoundBox *bb = BKE_volume_boundbox_get(ob); + float bb_size[3]; + sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]); + size_to_mat4(bounds_to_object, bb_size); + copy_v3_v3(bounds_to_object[3], bb->vec[0]); + + invert_m4_m4(first_drw_grid->object_to_bounds, bounds_to_object); + DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_bounds); } - /* If shader failed to compile or is currently compiling. */ - if (status != GPU_MAT_SUCCESS) { - return; + else { + /* All grid transforms are equal, we can transform to texture space immediately. */ + DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_texture); } - DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps); - - BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, &texcosize); + /* Don't use orco transform here, only matrix. */ + DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoLoc", (float[3]){0.5f, 0.5f, 0.5f}); + DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoSize", (float[3]){0.5f, 0.5f, 0.5f}); + + /* Bind volume grid textures. */ + LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { + VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name); + DRWVolumeGrid *drw_grid = (volume_grid) ? + DRW_volume_batch_cache_get_grid(volume, volume_grid) : + NULL; + + DRW_shgroup_uniform_texture( + grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_density); + + if (drw_grid && multiple_transforms) { + /* Specify per-volume tranform matrix that is applied after the + * transform from object to bounds. */ + mul_m4_m4m4(drw_grid->bounds_to_texture, drw_grid->object_to_texture, bounds_to_object); + DRW_shgroup_uniform_mat4(grp, gpu_grid->transform_name, drw_grid->bounds_to_texture); + } + } - /* TODO(fclem) remove those "unnecessary" UBOs */ - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + return true; +} - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1); - DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1); +static bool eevee_volume_object_mesh_init(Scene *scene, + Object *ob, + ListBase *gpu_grids, + DRWShadingGroup *grp) +{ + static const float white[3] = {1.0f, 1.0f, 1.0f}; + ModifierData *md = NULL; - ListBase gpu_grids = GPU_material_volume_grids(mat); /* Smoke Simulation */ if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Fluid)) && @@ -458,7 +490,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, /* Don't try to show liquid domains here. */ if (!mds->fluid || !(mds->type == FLUID_DOMAIN_TYPE_GAS)) { - return; + return false; } /* Don't show smoke before simulation starts, this could be made an option in the future. */ @@ -479,7 +511,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd)); } - for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) { + LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { if (STREQ(gpu_grid->name, "density")) { DRW_shgroup_uniform_texture_ref(grp, gpu_grid->sampler_name, @@ -510,10 +542,85 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &mds->flame_ignition, 1); } else { - for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) { + LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density); } - DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1); + } + + /* Transform for mesh volumes. */ + static const float unit_mat[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}; + float *texco_loc, *texco_size; + BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texco_loc, &texco_size); + + DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", unit_mat); + DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texco_loc, 1); + DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texco_size, 1); + + return true; +} + +void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + Scene *scene, + Object *ob) +{ + Material *ma = BKE_object_material_get(ob, 1); + + if (ma == NULL) { + if (ob->type == OB_VOLUME) { + ma = BKE_material_default_volume(); + } + else { + return; + } + } + + float size[3]; + mat4_to_size(size, ob->obmat); + /* Check if any of the axes have 0 length. (see T69070) */ + const float epsilon = 1e-8f; + if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) { + return; + } + + struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); + eGPUMaterialStatus status = GPU_material_status(mat); + + if (status == GPU_MAT_QUEUED) { + vedata->stl->g_data->queued_shaders_count++; + } + /* If shader failed to compile or is currently compiling. */ + if (status != GPU_MAT_SUCCESS) { + return; + } + + DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps); + + /* TODO(fclem) remove those "unnecessary" UBOs */ + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + + ListBase gpu_grids = GPU_material_volume_grids(mat); + + if (ob->type == OB_VOLUME) { + if (!eevee_volume_object_grids_init(ob, &gpu_grids, grp)) { + return; + } + } + else { + if (!eevee_volume_object_mesh_init(scene, ob, &gpu_grids, grp)) { + return; + } } /* TODO Reduce to number of slices intersecting. */ @@ -757,6 +864,7 @@ void EEVEE_volumes_free(void) DRW_TEXTURE_FREE_SAFE(e_data.dummy_density); DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_color); DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh); DRW_SHADER_FREE_SAFE(e_data.scatter_sh); diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index 2b1ae60654e..f5e92cd7495 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -7,6 +7,7 @@ #ifdef MESH_SHADER uniform vec3 volumeOrcoLoc; uniform vec3 volumeOrcoSize; +uniform mat4 volumeObjectToTexture; #endif flat in int slice; @@ -35,8 +36,10 @@ void main() worldPosition = point_view_to_world(viewPosition); #ifdef MESH_SHADER volumeObjectLocalCoord = point_world_to_object(worldPosition); + /* TODO: redundant transform */ volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0); + volumeObjectLocalCoord = (volumeObjectToTexture * vec4(volumeObjectLocalCoord, 1.0)).xyz; if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) || any(greaterThan(volumeObjectLocalCoord, vec3(1.0)))) diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index 740ca42800e..9b900a53d8d 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -161,6 +161,7 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_motion_path_cache_init(vedata); OVERLAY_outline_cache_init(vedata); OVERLAY_particle_cache_init(vedata); + OVERLAY_pointcloud_cache_init(vedata); OVERLAY_wireframe_cache_init(vedata); } @@ -205,6 +206,11 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj return pd->ctx_mode == CTX_MODE_EDIT_METABALL; case OB_FONT: return pd->ctx_mode == CTX_MODE_EDIT_TEXT; + case OB_HAIR: + case OB_POINTCLOUD: + case OB_VOLUME: + /* No edit mode yet. */ + return false; } } return false; @@ -223,8 +229,16 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) const bool in_paint_mode = (ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT); const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL); - const bool has_surface = ELEM( - ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT, OB_GPENCIL); + const bool has_surface = ELEM(ob->type, + OB_MESH, + OB_CURVE, + OB_SURF, + OB_MBALL, + OB_FONT, + OB_GPENCIL, + OB_HAIR, + OB_POINTCLOUD, + OB_VOLUME); const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE)); const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION); const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0; @@ -361,6 +375,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) OVERLAY_particle_cache_populate(vedata, ob); } + /* TODO: these should not be overlays, just here for testing since it's + * easier to implement than integrating it into eevee/workbench. */ + if (ob->type == OB_POINTCLOUD) { + OVERLAY_pointcloud_cache_populate(vedata, ob); + } + /* Relationship, object center, bounbox ... */ if (!pd->hide_overlays) { OVERLAY_extra_cache_populate(vedata, ob); @@ -434,6 +454,7 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_armature_draw(vedata); OVERLAY_particle_draw(vedata); OVERLAY_metaball_draw(vedata); + OVERLAY_pointcloud_draw(vedata); OVERLAY_gpencil_draw(vedata); OVERLAY_extra_draw(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index 53550fb115e..4c525acd5be 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -475,13 +475,25 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons texcosize = mb->size; break; } + case ID_HA: + case ID_PT: + case ID_VO: { + /* No user defined texture space support. */ + break; + } default: BLI_assert(0); } float mat[4][4]; - size_to_mat4(mat, texcosize); - copy_v3_v3(mat[3], texcoloc); + + if (texcoloc != NULL && texcosize != NULL) { + size_to_mat4(mat, texcosize); + copy_v3_v3(mat[3], texcoloc); + } + else { + unit_m4(mat); + } mul_m4_m4m4(mat, ob->obmat, mat); diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 167a8e940df..de35d4f760e 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -95,6 +95,7 @@ typedef struct OVERLAY_PassList { DRWPass *paint_color_ps; DRWPass *paint_overlay_ps; DRWPass *particle_ps; + DRWPass *pointcloud_ps; DRWPass *sculpt_mask_ps; DRWPass *wireframe_ps; DRWPass *wireframe_xray_ps; @@ -251,6 +252,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *paint_face_grp; DRWShadingGroup *particle_dots_grp; DRWShadingGroup *particle_shapes_grp; + DRWShadingGroup *pointcloud_dots_grp; DRWShadingGroup *sculpt_mask_grp; DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */ DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */ @@ -532,6 +534,10 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata); void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_particle_draw(OVERLAY_Data *vedata); +void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata); +void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata); + void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata); void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_sculpt_draw(OVERLAY_Data *vedata); @@ -597,6 +603,7 @@ GPUShader *OVERLAY_shader_paint_weight(void); GPUShader *OVERLAY_shader_paint_wire(void); GPUShader *OVERLAY_shader_particle_dot(void); GPUShader *OVERLAY_shader_particle_shape(void); +GPUShader *OVERLAY_shader_pointcloud_dot(void); GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); GPUShader *OVERLAY_shader_wireframe(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index d5509c7f56b..0b2f98294ec 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -102,6 +102,8 @@ extern char datatoc_paint_weight_vert_glsl[]; extern char datatoc_paint_wire_vert_glsl[]; extern char datatoc_particle_vert_glsl[]; extern char datatoc_particle_frag_glsl[]; +extern char datatoc_pointcloud_vert_glsl[]; +extern char datatoc_pointcloud_frag_glsl[]; extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_volume_velocity_vert_glsl[]; extern char datatoc_wireframe_vert_glsl[]; @@ -184,6 +186,7 @@ typedef struct OVERLAY_Shaders { GPUShader *paint_wire; GPUShader *particle_dot; GPUShader *particle_shape; + GPUShader *pointcloud_dot; GPUShader *sculpt_mask; GPUShader *uniform_color; GPUShader *volume_velocity_needle_sh; @@ -1272,6 +1275,25 @@ GPUShader *OVERLAY_shader_particle_shape(void) return sh_data->particle_shape; } +GPUShader *OVERLAY_shader_pointcloud_dot(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + if (!sh_data->pointcloud_dot) { + sh_data->pointcloud_dot = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg->lib, + datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_pointcloud_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_pointcloud_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg->def, "#define USE_DOTS\n", NULL}, + }); + } + return sh_data->pointcloud_dot; +} + GPUShader *OVERLAY_shader_sculpt_mask(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index 6b0e5e0b72e..cdf8005b827 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -22,6 +22,7 @@ #include "DNA_mesh_types.h" #include "DNA_view3d_types.h" +#include "DNA_volume_types.h" #include "BKE_curve.h" #include "BKE_displist.h" @@ -163,6 +164,20 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, } } + if (use_wire && ob->type == OB_VOLUME) { + /* Volume object as points exception. */ + Volume *volume = ob->data; + if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) { + float *color; + OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob); + DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); + + struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob); + OVERLAY_extra_loose_points(cb, geom, ob->obmat, color); + return; + } + } + const bool is_edit_mode = DRW_object_is_in_edit_mode(ob); bool has_edit_mesh_cage = false; if (is_mesh && is_edit_mode) { diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index e957f8bbe9c..0c2b7850f94 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -11,6 +11,7 @@ uniform sampler3D shadowTexture; uniform sampler3D flameTexture; uniform sampler1D flameColorTexture; uniform sampler1D transferTexture; +uniform mat4 volumeObjectToTexture; uniform int samplesLen = 256; uniform float noiseOfs = 0.0; @@ -110,20 +111,24 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) scattering = tval.rgb * 1500.0; extinction = max(1e-4, tval.a * 50.0); #else +# ifdef VOLUME_SMOKE float flame = sample_volume_texture(flameTexture, co).r; vec4 emission = texture(flameColorTexture, flame); +# endif + vec3 density = sample_volume_texture(densityTexture, co).rgb; float shadows = sample_volume_texture(shadowTexture, co).r; - vec4 density = sample_volume_texture(densityTexture, co); /* rgb: color, a: density */ - scattering = density.rgb * densityScale; + scattering = density * densityScale; extinction = max(1e-4, dot(scattering, vec3(0.33333))); scattering *= activeColor; /* Scale shadows in log space and clamp them to avoid completely black shadows. */ scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI; +# ifdef VOLUME_SMOKE /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0; +# endif #endif } @@ -201,9 +206,16 @@ void main() vec3 ls_ray_ori = point_view_to_object(vs_ray_ori); vec3 ls_ray_end = point_view_to_object(vs_ray_end); +# ifdef VOLUME_SMOKE ls_ray_dir = (OrcoTexCoFactors[0].xyz + ls_ray_dir * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0; ls_ray_ori = (OrcoTexCoFactors[0].xyz + ls_ray_ori * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0; ls_ray_end = (OrcoTexCoFactors[0].xyz + ls_ray_end * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0; +# else + ls_ray_dir = (volumeObjectToTexture * vec4(ls_ray_dir, 1.0)).xyz * 2.0f - 1.0; + ls_ray_ori = (volumeObjectToTexture * vec4(ls_ray_ori, 1.0)).xyz * 2.0f - 1.0; + ls_ray_end = (volumeObjectToTexture * vec4(ls_ray_end, 1.0)).xyz * 2.0f - 1.0; +# endif + ls_ray_dir -= ls_ray_ori; /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl index 1a32a202290..7327a92e04f 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -5,6 +5,8 @@ uniform float slicePosition; uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ +uniform mat4 volumeTextureToObject; + in vec3 pos; RESOURCE_ID_VARYING @@ -31,7 +33,12 @@ void main() #else vec3 final_pos = pos; #endif + +#ifdef VOLUME_SMOKE final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0].xyz) / OrcoTexCoFactors[1].xyz; +#else + final_pos = (volumeTextureToObject * vec4(final_pos * 0.5 + 0.5, 1.0)).xyz; +#endif gl_Position = point_object_to_ndc(final_pos); PASS_RESOURCE_ID diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 742489c7311..e9525af5682 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -33,8 +33,9 @@ #include "BKE_paint.h" #include "BKE_particle.h" -#include "DNA_image_types.h" #include "DNA_fluid_types.h" +#include "DNA_hair_types.h" +#include "DNA_image_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_node_types.h" @@ -192,12 +193,12 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd, Object *ob, + ParticleSystem *psys, ModifierData *md, eV3DShadingColorType color_type, - bool use_texpaint_mode) + bool use_texpaint_mode, + const int matnr) { - ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; - ParticleSettings *part = psys->part; const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; @@ -206,8 +207,8 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd, int interp = (imapaint && imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR : SHD_INTERP_CLOSEST; DRWShadingGroup *grp = (use_texpaint_mode) ? - workbench_image_hair_setup(wpd, ob, part->omat, ima, NULL, interp) : - workbench_material_hair_setup(wpd, ob, part->omat, color_type); + workbench_image_hair_setup(wpd, ob, matnr, ima, NULL, interp) : + workbench_material_hair_setup(wpd, ob, matnr, color_type); DRW_shgroup_hair_create_sub(ob, psys, md, grp); } @@ -244,14 +245,20 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd, color_type = V3D_SHADING_OBJECT_COLOR; } - *r_sculpt_pbvh = is_sculpt_pbvh; - *r_texpaint_mode = false; + if (r_sculpt_pbvh) { + *r_sculpt_pbvh = is_sculpt_pbvh; + } + if (r_texpaint_mode) { + *r_texpaint_mode = false; + } if (!is_sculpt_pbvh && !is_render) { /* Force texture or vertex mode if object is in paint mode. */ if (is_texpaint_mode && me && me->mloopuv) { color_type = V3D_SHADING_TEXTURE_COLOR; - *r_texpaint_mode = true; + if (r_texpaint_mode) { + *r_texpaint_mode = true; + } } else if (is_vertpaint_mode && me && me->mloopcol) { color_type = V3D_SHADING_VERTEX_COLOR; @@ -286,8 +293,8 @@ void workbench_cache_populate(void *ved, Object *ob) } if (ob->type == OB_MESH && ob->modifiers.first != NULL) { - bool use_sculpt_pbvh, use_texpaint_mode; - int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, NULL); + bool use_texpaint_mode; + int color_type = workbench_color_type_get(wpd, ob, NULL, &use_texpaint_mode, NULL); LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if (md->type != eModifierType_ParticleSystem) { @@ -301,7 +308,8 @@ void workbench_cache_populate(void *ved, Object *ob) const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; if (draw_as == PART_DRAW_PATH) { - workbench_cache_hair_populate(wpd, ob, md, color_type, use_texpaint_mode); + workbench_cache_hair_populate( + wpd, ob, psys, md, color_type, use_texpaint_mode, part->omat); } } } @@ -311,7 +319,7 @@ void workbench_cache_populate(void *ved, Object *ob) if (md && modifier_isEnabled(wpd->scene, md, eModifierMode_Realtime)) { FluidModifierData *fmd = (FluidModifierData *)md; if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) { - workbench_volume_cache_populate(vedata, wpd->scene, ob, md); + workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR); return; /* Do not draw solid in this case. */ } } @@ -325,7 +333,7 @@ void workbench_cache_populate(void *ved, Object *ob) return; } - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_POINTCLOUD)) { bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false; eV3DShadingColorType color_type = workbench_color_type_get( wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow); @@ -344,6 +352,16 @@ void workbench_cache_populate(void *ved, Object *ob) workbench_shadow_cache_populate(vedata, ob, has_transp_mat); } } + else if (ob->type == OB_HAIR) { + int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL); + workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, HAIR_MATERIAL_NR); + } + else if (ob->type == OB_VOLUME) { + if (wpd->shading.type != OB_WIRE) { + int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL); + workbench_volume_cache_populate(vedata, wpd->scene, ob, NULL, color_type); + } + } } void workbench_cache_finish(void *ved) diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index a68b66e0f85..49becf93f48 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -101,6 +101,7 @@ typedef struct WORKBENCH_TextureList { struct GPUTexture *smaa_area_tx; struct GPUTexture *dummy_image_tx; struct GPUTexture *dummy_volume_tx; + struct GPUTexture *dummy_shadow_tx; struct GPUTexture *dummy_coba_tx; } WORKBENCH_TextureList; @@ -405,7 +406,7 @@ GPUShader *workbench_shader_outline_get(void); GPUShader *workbench_shader_antialiasing_accumulation_get(void); GPUShader *workbench_shader_antialiasing_get(int stage); -GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic); +GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke); void workbench_shader_depth_of_field_get(GPUShader **prepare_sh, GPUShader **downsample_sh, @@ -479,7 +480,8 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata); void workbench_volume_cache_populate(WORKBENCH_Data *vedata, struct Scene *UNUSED(scene), struct Object *ob, - struct ModifierData *md); + struct ModifierData *md, + eV3DShadingColorType color_type); void workbench_volume_draw_pass(WORKBENCH_Data *vedata); void workbench_volume_draw_finish(WORKBENCH_Data *vedata); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 14a980fe628..2e796056029 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -106,7 +106,7 @@ static struct { struct GPUShader *aa_accum_sh; struct GPUShader *smaa_sh[3]; - struct GPUShader *volume_sh[2][2][2]; + struct GPUShader *volume_sh[2][2][2][2]; struct DRWShaderLibrary *lib; } e_data = {{{{NULL}}}}; @@ -448,9 +448,9 @@ GPUShader *workbench_shader_antialiasing_get(int stage) return e_data.smaa_sh[stage]; } -GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic) +GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke) { - GPUShader **shader = &e_data.volume_sh[slice][coba][cubic]; + GPUShader **shader = &e_data.volume_sh[slice][coba][cubic][smoke]; if (*shader == NULL) { DynStr *ds = BLI_dynstr_new(); @@ -464,6 +464,9 @@ GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic) if (cubic) { BLI_dynstr_append(ds, "#define USE_TRICUBIC\n"); } + if (smoke) { + BLI_dynstr_append(ds, "#define VOLUME_SMOKE\n"); + } char *defines = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -513,7 +516,7 @@ void workbench_shader_free(void) DRW_SHADER_FREE_SAFE(sh_array[j]); } for (int j = 0; j < sizeof(e_data.volume_sh) / sizeof(void *); j++) { - struct GPUShader **sh_array = &e_data.volume_sh[0][0][0]; + struct GPUShader **sh_array = &e_data.volume_sh[0][0][0][0]; DRW_SHADER_FREE_SAFE(sh_array[j]); } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index a3072b834bd..1eccc99d9e9 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -22,16 +22,20 @@ #include "workbench_private.h" -#include "BKE_object.h" -#include "BKE_fluid.h" +#include "DNA_fluid_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_force_types.h" +#include "DNA_volume_types.h" #include "BLI_rand.h" #include "BLI_dynstr.h" #include "BLI_string_utils.h" -#include "DNA_modifier_types.h" -#include "DNA_object_force_types.h" -#include "DNA_fluid_types.h" +#include "BKE_fluid.h" +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_volume.h" +#include "BKE_volume_render.h" #include "GPU_draw.h" @@ -40,9 +44,11 @@ void workbench_volume_engine_init(WORKBENCH_Data *vedata) WORKBENCH_TextureList *txl = vedata->txl; if (txl->dummy_volume_tx == NULL) { - float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, pixel, NULL); - txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, pixel, NULL); + float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float one[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, zero, NULL); + txl->dummy_shadow_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, one, NULL); + txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, zero, NULL); } } @@ -54,10 +60,9 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata) vedata->stl->wpd->volumes_do = false; } -void workbench_volume_cache_populate(WORKBENCH_Data *vedata, - Scene *UNUSED(scene), - Object *ob, - ModifierData *md) +static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata, + Object *ob, + ModifierData *md) { FluidModifierData *mmd = (FluidModifierData *)md; FluidDomainSettings *mds = mmd->domain; @@ -90,8 +95,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, const bool use_slice = (mds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED && mds->axis_slice_method == AXIS_SLICE_SINGLE); const bool cubic_interp = (mds->interp_method == VOLUME_INTERP_CUBIC); - - GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp); + GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp, true); if (use_slice) { float invviewmat[4][4]; @@ -162,6 +166,107 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(mmd)); } +static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd, + Object *ob, + eV3DShadingColorType color_type, + float color[3]) +{ + Material *ma = BKE_object_material_get(ob, VOLUME_MATERIAL_NR); + WORKBENCH_UBO_Material ubo_data; + workbench_material_ubo_data(wpd, ob, ma, &ubo_data, color_type); + copy_v3_v3(color, ubo_data.base_color); +} + +static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata, + Object *ob, + eV3DShadingColorType color_type) +{ + /* Create 3D textures. */ + Volume *volume = ob->data; + BKE_volume_load(volume, G.main); + VolumeGrid *volume_grid = BKE_volume_grid_active_get(volume); + if (volume_grid == NULL) { + return; + } + DRWVolumeGrid *grid = DRW_volume_batch_cache_get_grid(volume, volume_grid); + if (grid == NULL) { + return; + } + + WORKBENCH_PrivateData *wpd = vedata->stl->wpd; + WORKBENCH_TextureList *txl = vedata->txl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + wpd->volumes_do = true; + + /* Create shader. */ + GPUShader *sh = workbench_shader_volume_get(false, false, false, false); + + /* Compute color. */ + float color[3]; + workbench_volume_material_color(wpd, ob, color_type, color); + + /* Combined texture to object, and object to world transform. */ + float texture_to_world[4][4]; + mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object); + + /* Compute world space dimensions for step size. */ + float world_size[3]; + mat4_to_size(world_size, texture_to_world); + abs_v3(world_size); + + /* Compute step parameters. */ + double noise_ofs; + BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs); + float step_length, max_slice; + int resolution[3]; + GPU_texture_get_mipmap_size(grid->texture, 0, resolution); + float slice_ct[3] = {resolution[0], resolution[1], resolution[2]}; + mul_v3_fl(slice_ct, max_ff(0.001f, 5.0f)); + max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]); + invert_v3(slice_ct); + mul_v3_v3(slice_ct, world_size); + step_length = len_v3(slice_ct); + + /* Compute density scale. */ + const float density_scale = volume->display.density; + + /* Set uniforms. */ + DRWShadingGroup *grp = DRW_shgroup_create(sh, vedata->psl->volume_ps); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice); + DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length); + DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs); + DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); + + DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture); + /* TODO: implement shadow texture, see manta_smoke_calc_transparency. */ + DRW_shgroup_uniform_texture(grp, "shadowTexture", txl->dummy_shadow_tx); + DRW_shgroup_uniform_vec3_copy(grp, "activeColor", color); + + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_float_copy(grp, "densityScale", density_scale); + + DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", grid->object_to_texture); + DRW_shgroup_uniform_mat4(grp, "volumeTextureToObject", grid->texture_to_object); + + DRW_shgroup_call(grp, DRW_cache_cube_get(), ob); +} + +void workbench_volume_cache_populate(WORKBENCH_Data *vedata, + Scene *UNUSED(scene), + Object *ob, + ModifierData *md, + eV3DShadingColorType color_type) +{ + if (md == NULL) { + workbench_volume_object_cache_populate(vedata, ob, color_type); + } + else { + workbench_volume_modifier_cache_populate(vedata, ob, md); + } +} + void workbench_volume_draw_pass(WORKBENCH_Data *vedata) { WORKBENCH_PassList *psl = vedata->psl; @@ -189,4 +294,4 @@ void workbench_volume_draw_finish(WORKBENCH_Data *vedata) GPU_free_smoke(mmd); } BLI_freelistN(&wpd->smoke_domains); -}
\ No newline at end of file +} |