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:
authorClément Foucault <foucault.clem@gmail.com>2022-04-19 13:01:16 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-04-19 13:09:18 +0300
commitfa3bd17ae87301ca198d16d2dc7d2432548f34f9 (patch)
treec08eb8740784799dd3bf9517f4eb4380bc4e6cab /source/blender/draw/intern/draw_volume.cc
parent1e3f4c70ab56578b8b0e0056870bd17cc118982a (diff)
GPU: Replace `GPUMaterialVolumeGrid` by `GPUMaterialAttribute`
This is to make the codegen and shading nodes object type agnostic. This is essential for flexibility of the engine to use the nodetree as it see fits. The essential volume attributes struct properties are moved to the `GPUMaterialAttribute` which see its final input name set on creation. The binding process is centralized into `draw_volume.cc` to avoid duplicating the code between multiple engines. It mimics the hair attributes process. Volume object grid transforms and other per object uniforms are packed into one UBO per object. The grid transform is now based on object which simplify the matrix preparations. This also gets rid of the double transforms and use object info orco factors for volume objects. Tagging @brecht because he did the initial implementation of Volume Grids.
Diffstat (limited to 'source/blender/draw/intern/draw_volume.cc')
-rw-r--r--source/blender/draw/intern/draw_volume.cc266
1 files changed, 266 insertions, 0 deletions
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);
+ }
+}