diff options
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/DRW_gpu_wrapper.hh | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 17 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 8 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 12 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_shader_shared.h | 16 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_volume.cc | 266 | ||||
-rw-r--r-- | source/blender/draw/intern/shaders/common_attribute_lib.glsl | 12 | ||||
-rw-r--r-- | source/blender/draw/intern/shaders/draw_object_infos_info.hh | 4 |
9 files changed, 339 insertions, 1 deletions
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_common.h b/source/blender/draw/intern/draw_common.h index 566e68a5c84..af2efd338e4 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -21,6 +21,7 @@ struct Object; struct ParticleSystem; struct RegionView3D; struct ViewLayer; +struct Scene; struct DRWData; /* Keep in sync with globalsBlock in shaders */ @@ -74,6 +75,22 @@ void DRW_hair_init(void); void DRW_hair_update(void); void DRW_hair_free(void); +/* draw_volume.cc */ + +/** + * Add attributes bindings of volume grids to an exhisting 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. */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 441628f2490..e0dfc29b966 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); } @@ -1650,6 +1651,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_debug_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); /* No frame-buffer allowed before drawing. */ @@ -2021,6 +2023,7 @@ void DRW_render_object_iter( { const DRWContextState *draw_ctx = DRW_context_state_get(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); drw_task_graph_init(); @@ -2077,6 +2080,7 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, drw_manager_init(&DST, NULL, NULL); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); ViewportEngineData *data = DRW_view_data_engine_data_get_ensure(DST.view_data_active, @@ -2111,6 +2115,7 @@ void DRW_cache_restart(void) DST.buffer_finish_called = false; DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); } @@ -2429,6 +2434,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); { @@ -2602,6 +2608,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); { @@ -3027,6 +3034,7 @@ void DRW_engines_free(void) DRW_shaders_free(); DRW_hair_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 e861d91d47e..8812f112014 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -527,6 +527,8 @@ 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. */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 39f083aaf96..7c779b42c73 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; @@ -614,7 +624,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) drw_call_calc_orco(ob, ob_infos->orcotexfac); /* Random float value. */ uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : + DST.dupli_source->random_id : /* TODO(fclem): this is rather costly to do at runtime. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h index 58875c0496a..d2e51b67468 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 alignement. 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..c9c8acaef40 --- /dev/null +++ b/source/blender/draw/intern/draw_volume.cc @@ -0,0 +1,266 @@ +/* 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(void) +{ + 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); + 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) ? 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 = NULL; + + 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 != 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 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. */ + int grid_id = 0; + 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); + } + else if (ob->type == OB_VOLUME) { + return drw_volume_object_grids_init(ob, &attrs, shgrp); + } + else { + return drw_volume_object_mesh_init(scene, ob, &attrs, shgrp); + } +} 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); |