Blender  V3.3
draw_volume.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2022 Blender Foundation. All rights reserved. */
3 
10 #include "DRW_gpu_wrapper.hh"
11 #include "DRW_render.h"
12 
13 #include "DNA_fluid_types.h"
14 #include "DNA_volume_types.h"
15 
16 #include "BKE_fluid.h"
17 #include "BKE_global.h"
18 #include "BKE_mesh.h"
19 #include "BKE_modifier.h"
20 #include "BKE_volume.h"
21 #include "BKE_volume_render.h"
22 
23 #include "GPU_material.h"
24 
25 #include "draw_common.h"
26 #include "draw_manager.h"
27 
28 using namespace blender;
29 using namespace blender::draw;
31 
32 static struct {
35  float dummy_grid_mat[4][4];
36 } g_data = {};
37 
40  uint used = 0;
41 
43  {
44  for (VolumeInfosBuf *ubo : ubos) {
45  delete ubo;
46  }
47  }
48 
49  void reset()
50  {
51  used = 0;
52  }
53 
55  {
56  if (used >= ubos.size()) {
57  VolumeInfosBuf *buf = new VolumeInfosBuf();
58  ubos.append(buf);
59  }
60  return ubos[used++];
61  }
62 };
63 
65 {
66  delete reinterpret_cast<VolumeUniformBufPool *>(pool);
67 }
68 
70 {
71  const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
72  const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
73  g_data.dummy_zero = GPU_texture_create_3d(
74  "dummy_zero", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, zero);
75  g_data.dummy_one = GPU_texture_create_3d(
76  "dummy_one", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, one);
77  GPU_texture_wrap_mode(g_data.dummy_zero, true, true);
78  GPU_texture_wrap_mode(g_data.dummy_one, true, true);
79 
80  memset(g_data.dummy_grid_mat, 0, sizeof(g_data.dummy_grid_mat));
81 }
82 
83 void DRW_volume_free(void)
84 {
85  GPU_TEXTURE_FREE_SAFE(g_data.dummy_zero);
86  GPU_TEXTURE_FREE_SAFE(g_data.dummy_one);
87 }
88 
90 {
91  if (g_data.dummy_one == nullptr) {
93  }
94 
95  switch (default_value) {
96  case GPU_DEFAULT_0:
97  return g_data.dummy_zero;
98  case GPU_DEFAULT_1:
99  return g_data.dummy_one;
100  }
101  return g_data.dummy_zero;
102 }
103 
104 void DRW_volume_init(DRWData *drw_data)
105 {
106  if (drw_data->volume_grids_ubos == nullptr) {
107  drw_data->volume_grids_ubos = new VolumeUniformBufPool();
108  }
110  pool->reset();
111 
112  if (g_data.dummy_one == nullptr) {
114  }
115 }
116 
118  ListBase *attrs,
119  DRWShadingGroup *grp)
120 {
122  VolumeInfosBuf &volume_infos = *pool->alloc();
123 
124  Volume *volume = (Volume *)ob->data;
125  BKE_volume_load(volume, G.main);
126 
127  grp = DRW_shgroup_create_sub(grp);
128 
129  volume_infos.density_scale = BKE_volume_density_scale(volume, ob->obmat);
130  volume_infos.color_mul = float4(1.0f);
131  volume_infos.temperature_mul = 1.0f;
132  volume_infos.temperature_bias = 0.0f;
133 
134  /* Bind volume grid textures. */
135  int grid_id = 0, grids_len = 0;
136  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
137  const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, attr->name);
138  const DRWVolumeGrid *drw_grid = (volume_grid) ?
139  DRW_volume_batch_cache_get_grid(volume, volume_grid) :
140  nullptr;
141  /* Count number of valid attributes. */
142  grids_len += int(volume_grid != nullptr);
143 
144  /* Handle 3 cases here:
145  * - Grid exists and texture was loaded -> use texture.
146  * - Grid exists but has zero size or failed to load -> use zero.
147  * - Grid does not exist -> use default value. */
148  const GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture :
149  (volume_grid) ? g_data.dummy_zero :
150  grid_default_texture(attr->default_value);
151  DRW_shgroup_uniform_texture(grp, attr->input_name, grid_tex);
152 
153  copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(),
154  (drw_grid) ? drw_grid->object_to_texture : g_data.dummy_grid_mat);
155  }
156  /* Render nothing if there is no attribute for the shader to render.
157  * This also avoids an assert caused by the bounding box being zero in size. */
158  if (grids_len == 0) {
159  return nullptr;
160  }
161 
162  volume_infos.push_update();
163 
164  DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos);
165 
166  return grp;
167 }
168 
170  Object *ob,
171  ListBase *attrs,
172  DRWShadingGroup *grp)
173 {
175  VolumeInfosBuf &volume_infos = *pool->alloc();
176 
177  ModifierData *md = nullptr;
178 
179  volume_infos.density_scale = 1.0f;
180  volume_infos.color_mul = float4(1.0f);
181  volume_infos.temperature_mul = 1.0f;
182  volume_infos.temperature_bias = 0.0f;
183 
184  /* Smoke Simulation */
187  ((FluidModifierData *)md)->domain != nullptr) {
189  FluidDomainSettings *fds = fmd->domain;
190 
191  /* Don't try to show liquid domains here. */
192  if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) {
193  return nullptr;
194  }
195 
196  if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS)) {
198  }
199 
200  grp = DRW_shgroup_create_sub(grp);
201 
202  int grid_id = 0;
203  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
204  if (STREQ(attr->name, "density")) {
206  grp, attr->input_name, fds->tex_density ? &fds->tex_density : &g_data.dummy_one);
207  }
208  else if (STREQ(attr->name, "color")) {
210  grp, attr->input_name, fds->tex_color ? &fds->tex_color : &g_data.dummy_one);
211  }
212  else if (STR_ELEM(attr->name, "flame", "temperature")) {
214  grp, attr->input_name, fds->tex_flame ? &fds->tex_flame : &g_data.dummy_zero);
215  }
216  else {
218  grp, attr->input_name, grid_default_texture(attr->default_value));
219  }
220  copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat);
221  }
222 
223  bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
225  if (use_constant_color) {
226  volume_infos.color_mul = float4(UNPACK3(fds->active_color), 1.0f);
227  }
228 
229  /* Output is such that 0..1 maps to 0..1000K */
230  volume_infos.temperature_mul = fds->flame_max_temp - fds->flame_ignition;
231  volume_infos.temperature_bias = fds->flame_ignition;
232  }
233  else {
234  grp = DRW_shgroup_create_sub(grp);
235 
236  int grid_id = 0;
237  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
239  grp, attr->input_name, grid_default_texture(attr->default_value));
240  copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat);
241  }
242  }
243 
244  volume_infos.push_update();
245 
246  DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos);
247 
248  return grp;
249 }
250 
252 {
253  /* Bind default volume grid textures. */
254  LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) {
255  DRW_shgroup_uniform_texture(grp, attr->input_name, grid_default_texture(attr->default_value));
256  }
257  return grp;
258 }
259 
261  Object *ob,
262  DRWShadingGroup *shgrp,
263  GPUMaterial *gpu_material)
264 {
265  ListBase attrs = GPU_material_attributes(gpu_material);
266 
267  if (ob == nullptr) {
268  return drw_volume_world_grids_init(&attrs, shgrp);
269  }
270  if (ob->type == OB_VOLUME) {
271  return drw_volume_object_grids_init(ob, &attrs, shgrp);
272  }
273  return drw_volume_object_mesh_init(scene, ob, &attrs, shgrp);
274 }
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
Volume data-block.
const VolumeGrid * BKE_volume_grid_find_for_read(const struct Volume *volume, const char *name)
bool BKE_volume_load(const struct Volume *volume, const struct Main *bmain)
Volume data-block rendering and viewport drawing utilities.
float BKE_volume_density_scale(const struct Volume *volume, const float matrix[4][4])
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
#define STR_ELEM(...)
Definition: BLI_string.h:539
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK3(a)
#define STREQ(a, b)
@ FLUID_DOMAIN_TYPE_GAS
@ FLUID_DOMAIN_USE_NOISE
@ FLUID_DOMAIN_ACTIVE_COLORS
@ FLUID_DOMAIN_ACTIVE_COLOR_SET
@ eModifierMode_Realtime
@ eModifierType_Fluid
@ OB_VOLUME
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
eGPUDefaultValue
Definition: GPU_material.h:120
@ GPU_DEFAULT_1
Definition: GPU_material.h:122
@ GPU_DEFAULT_0
Definition: GPU_material.h:121
ListBase GPU_material_attributes(GPUMaterial *material)
Definition: gpu_material.c:216
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
Definition: gpu_texture.cc:546
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:171
#define GPU_TEXTURE_FREE_SAFE(texture)
Definition: GPU_texture.h:40
@ GPU_RGBA8
Definition: GPU_texture.h:87
GPUTexture * GPU_texture_create_3d(const char *name, int w, int h, int d, int mip_len, eGPUTextureFormat texture_format, eGPUDataFormat data_format, const void *data)
Definition: gpu_texture.cc:309
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
Scene scene
DRWVolumeGrid * DRW_volume_batch_cache_get_grid(struct Volume *volume, const struct VolumeGrid *grid)
void DRW_smoke_ensure(struct FluidModifierData *fmd, int highres)
Definition: draw_fluid.c:453
DRWManager DST
Definition: draw_manager.c:104
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_volume_free(void)
Definition: draw_volume.cc:83
void DRW_volume_ubos_pool_free(void *pool)
Definition: draw_volume.cc:64
void DRW_volume_init(DRWData *drw_data)
Definition: draw_volume.cc:104
static DRWShadingGroup * drw_volume_world_grids_init(ListBase *attrs, DRWShadingGroup *grp)
Definition: draw_volume.cc:251
static DRWShadingGroup * drw_volume_object_mesh_init(Scene *scene, Object *ob, ListBase *attrs, DRWShadingGroup *grp)
Definition: draw_volume.cc:169
static DRWShadingGroup * drw_volume_object_grids_init(Object *ob, ListBase *attrs, DRWShadingGroup *grp)
Definition: draw_volume.cc:117
static struct @318 g_data
static void drw_volume_globals_init()
Definition: draw_volume.cc:69
GPUTexture * dummy_zero
Definition: draw_volume.cc:33
GPUTexture * dummy_one
Definition: draw_volume.cc:34
static GPUTexture * grid_default_texture(eGPUDefaultValue default_value)
Definition: draw_volume.cc:89
DRWShadingGroup * DRW_shgroup_volume_create_sub(Scene *scene, Object *ob, DRWShadingGroup *shgrp, GPUMaterial *gpu_material)
Definition: draw_volume.cc:260
float dummy_grid_mat[4][4]
Definition: draw_volume.cc:35
blender::draw::UniformBuffer< VolumeInfos > VolumeInfosBuf
Definition: draw_volume.cc:30
#define G(x, y, z)
vec_base< float, 4 > float4
void * volume_grids_ubos
Definition: draw_manager.h:533
DRWData * vmempool
Definition: draw_manager.h:562
struct GPUTexture * texture
Definition: draw_cache.h:248
float object_to_texture[4][4]
Definition: draw_cache.h:252
struct GPUTexture * tex_density
struct GPUTexture * tex_color
struct MANTA * fluid
struct GPUTexture * tex_flame
struct FluidDomainSettings * domain
ustring name
Definition: graph/node.h:174
float obmat[4][4]
void * data
Vector< VolumeInfosBuf * > ubos
Definition: draw_volume.cc:39
VolumeInfosBuf * alloc()
Definition: draw_volume.cc:54