Blender  V3.3
workbench_volume.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2018 Blender Foundation. */
3 
8 #include "workbench_private.h"
9 
10 #include "DNA_fluid_types.h"
11 #include "DNA_modifier_types.h"
12 #include "DNA_object_force_types.h"
13 #include "DNA_volume_types.h"
14 
15 #include "BLI_dynstr.h"
16 #include "BLI_listbase.h"
17 #include "BLI_rand.h"
18 #include "BLI_string_utils.h"
19 
20 #include "BKE_fluid.h"
21 #include "BKE_global.h"
22 #include "BKE_object.h"
23 #include "BKE_volume.h"
24 #include "BKE_volume_render.h"
25 
27 {
28  WORKBENCH_TextureList *txl = vedata->txl;
29 
30  if (txl->dummy_volume_tx == NULL) {
31  const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
32  const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
34  "dummy_volume", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, zero);
36  "dummy_shadow", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, one);
37  txl->dummy_coba_tx = GPU_texture_create_1d("dummy_coba", 1, 1, GPU_RGBA8, zero);
38  }
39 }
40 
42 {
43  vedata->psl->volume_ps = DRW_pass_create(
45 
46  vedata->stl->wpd->volumes_do = false;
47 }
48 
50  Object *ob,
51  ModifierData *md)
52 {
54  FluidDomainSettings *fds = fmd->domain;
55  WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
56  WORKBENCH_TextureList *txl = vedata->txl;
58  DRWShadingGroup *grp = NULL;
59 
60  if (!fds->fluid) {
61  return;
62  }
63 
64  wpd->volumes_do = true;
65  if (fds->use_coba) {
67  }
68  else if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
70  }
71  else {
72  return;
73  }
74 
75  if ((!fds->use_coba && (fds->tex_density == NULL && fds->tex_color == NULL)) ||
76  (fds->use_coba && fds->tex_field == NULL)) {
77  return;
78  }
79 
80  const bool use_slice = (fds->axis_slice_method == AXIS_SLICE_SINGLE);
81  const bool show_phi = ELEM(fds->coba_field,
86  const bool show_flags = (fds->coba_field == FLUID_DOMAIN_FIELD_FLAGS);
87  const bool show_pressure = (fds->coba_field == FLUID_DOMAIN_FIELD_PRESSURE);
89 
92  interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
93  break;
95  interp_type = WORKBENCH_VOLUME_INTERP_CUBIC;
96  break;
98  interp_type = WORKBENCH_VOLUME_INTERP_CLOSEST;
99  break;
100  }
101 
102  GPUShader *sh = workbench_shader_volume_get(use_slice, fds->use_coba, interp_type, true);
103 
104  if (use_slice) {
105  float invviewmat[4][4];
106  DRW_view_viewmat_get(NULL, invviewmat, true);
107 
108  const int axis = (fds->slice_axis == SLICE_AXIS_AUTO) ?
109  axis_dominant_v3_single(invviewmat[2]) :
110  fds->slice_axis - 1;
111  float dim[3];
112  BKE_object_dimensions_get(ob, dim);
113  /* 0.05f to achieve somewhat the same opacity as the full view. */
114  float step_length = max_ff(1e-16f, dim[axis] * 0.05f);
115 
116  grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
117  DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
118  DRW_shgroup_uniform_float_copy(grp, "slicePosition", fds->slice_depth);
119  DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
120  DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
122  }
123  else {
124  double noise_ofs;
125  BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
126  float dim[3], step_length, max_slice;
127  float slice_count[3] = {fds->res[0], fds->res[1], fds->res[2]};
128  mul_v3_fl(slice_count, max_ff(0.001f, fds->slice_per_voxel));
129  max_slice = max_fff(slice_count[0], slice_count[1], slice_count[2]);
130  BKE_object_dimensions_get(ob, dim);
131  invert_v3(slice_count);
132  mul_v3_v3(dim, slice_count);
133  step_length = len_v3(dim);
134 
135  grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
136  DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
137  DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
138  DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
139  DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
141  }
142 
143  if (fds->use_coba) {
144  if (show_flags) {
145  DRW_shgroup_uniform_texture(grp, "flagTexture", fds->tex_field);
146  }
147  else {
148  DRW_shgroup_uniform_texture(grp, "densityTexture", fds->tex_field);
149  }
150  if (!show_phi && !show_flags && !show_pressure) {
151  DRW_shgroup_uniform_texture(grp, "transferTexture", fds->tex_coba);
152  }
153  DRW_shgroup_uniform_float_copy(grp, "gridScale", fds->grid_scale);
154  DRW_shgroup_uniform_bool_copy(grp, "showPhi", show_phi);
155  DRW_shgroup_uniform_bool_copy(grp, "showFlags", show_flags);
156  DRW_shgroup_uniform_bool_copy(grp, "showPressure", show_pressure);
157  }
158  else {
159  static float white[3] = {1.0f, 1.0f, 1.0f};
160  bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
163  grp, "densityTexture", (fds->tex_color) ? fds->tex_color : fds->tex_density);
164  DRW_shgroup_uniform_texture(grp, "shadowTexture", fds->tex_shadow);
166  grp, "flameTexture", (fds->tex_flame) ? fds->tex_flame : txl->dummy_volume_tx);
168  grp, "flameColorTexture", (fds->tex_flame) ? fds->tex_flame_coba : txl->dummy_coba_tx);
170  grp, "activeColor", (use_constant_color) ? fds->active_color : white, 1);
171  }
172  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
173  DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * fds->display_thickness);
174 
175  if (use_slice) {
177  }
178  else {
180  }
181 }
182 
184  Object *ob,
185  eV3DShadingColorType color_type,
186  float color[3])
187 {
189  WORKBENCH_UBO_Material ubo_data;
190  workbench_material_ubo_data(wpd, ob, ma, &ubo_data, color_type);
191  copy_v3_v3(color, ubo_data.base_color);
192 }
193 
195  Object *ob,
196  eV3DShadingColorType color_type)
197 {
198  /* Create 3D textures. */
199  Volume *volume = ob->data;
200  BKE_volume_load(volume, G.main);
201  const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
202  if (volume_grid == NULL) {
203  return;
204  }
205  DRWVolumeGrid *grid = DRW_volume_batch_cache_get_grid(volume, volume_grid);
206  if (grid == NULL) {
207  return;
208  }
209 
210  WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
211  WORKBENCH_TextureList *txl = vedata->txl;
213  DRWShadingGroup *grp = NULL;
214 
215  wpd->volumes_do = true;
216  const bool use_slice = (volume->display.axis_slice_method == AXIS_SLICE_SINGLE);
218 
221  interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
222  break;
224  interp_type = WORKBENCH_VOLUME_INTERP_CUBIC;
225  break;
227  interp_type = WORKBENCH_VOLUME_INTERP_CLOSEST;
228  break;
229  }
230 
231  /* Create shader. */
232  GPUShader *sh = workbench_shader_volume_get(use_slice, false, interp_type, false);
233 
234  /* Compute color. */
235  float color[3];
236  workbench_volume_material_color(wpd, ob, color_type, color);
237 
238  /* Combined texture to object, and object to world transform. */
239  float texture_to_world[4][4];
240  mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object);
241 
242  if (use_slice) {
243  float invviewmat[4][4];
244  DRW_view_viewmat_get(NULL, invviewmat, true);
245 
246  const int axis = (volume->display.slice_axis == SLICE_AXIS_AUTO) ?
247  axis_dominant_v3_single(invviewmat[2]) :
248  volume->display.slice_axis - 1;
249 
250  float dim[3];
251  BKE_object_dimensions_get(ob, dim);
252  /* 0.05f to achieve somewhat the same opacity as the full view. */
253  float step_length = max_ff(1e-16f, dim[axis] * 0.05f);
254 
255  const float slice_position = volume->display.slice_depth;
256 
257  grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
258  DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
259  DRW_shgroup_uniform_float_copy(grp, "slicePosition", slice_position);
260  DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
261  DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
263  }
264  else {
265  /* Compute world space dimensions for step size. */
266  float world_size[3];
267  mat4_to_size(world_size, texture_to_world);
268  abs_v3(world_size);
269 
270  /* Compute step parameters. */
271  double noise_ofs;
272  BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
273  float step_length, max_slice;
274  int resolution[3];
275  GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
276  float slice_count[3] = {resolution[0], resolution[1], resolution[2]};
277  mul_v3_fl(slice_count, max_ff(0.001f, 5.0f));
278  max_slice = max_fff(slice_count[0], slice_count[1], slice_count[2]);
279  invert_v3(slice_count);
280  mul_v3_v3(slice_count, world_size);
281  step_length = len_v3(slice_count);
282 
283  /* Set uniforms. */
284  grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
285  DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
286  DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
287  DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
288  DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
290  }
291 
292  /* Compute density scale. */
293  const float density_scale = volume->display.density *
294  BKE_volume_density_scale(volume, ob->obmat);
295 
296  DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture);
297  /* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
298  DRW_shgroup_uniform_texture(grp, "shadowTexture", txl->dummy_shadow_tx);
299  DRW_shgroup_uniform_vec3_copy(grp, "activeColor", color);
300 
301  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
302  DRW_shgroup_uniform_float_copy(grp, "densityScale", density_scale);
303 
304  DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", grid->object_to_texture);
305  DRW_shgroup_uniform_mat4(grp, "volumeTextureToObject", grid->texture_to_object);
306 
308 }
309 
311  Scene *UNUSED(scene),
312  Object *ob,
313  ModifierData *md,
314  eV3DShadingColorType color_type)
315 {
316  if (md == NULL) {
317  workbench_volume_object_cache_populate(vedata, ob, color_type);
318  }
319  else {
321  }
322 }
323 
325 {
326  WORKBENCH_PassList *psl = vedata->psl;
327  WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
329 
330  if (wpd->volumes_do) {
332  DRW_draw_pass(psl->volume_ps);
333  }
334 }
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
Definition: material.c:707
General operations, lookup, etc. for blender objects.
void BKE_object_dimensions_get(struct Object *ob, float r_vec[3])
Definition: object.cc:3786
Volume data-block.
const VolumeGrid * BKE_volume_grid_active_get_for_read(const struct Volume *volume)
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])
A dynamically sized string ADT.
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
MINLINE int axis_dominant_v3_single(const float vec[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void mat4_to_size(float size[3], const float M[4][4])
Definition: math_matrix.c:2138
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void abs_v3(float r[3])
MINLINE void invert_v3(float r[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
void BLI_halton_1d(unsigned int prime, double offset, int n, double *r)
Definition: rand.cc:287
#define UNUSED(x)
#define ELEM(...)
@ FLUID_DOMAIN_TYPE_GAS
FLUID_DisplayInterpolationMethod
@ FLUID_DISPLAY_INTERP_CLOSEST
@ FLUID_DISPLAY_INTERP_CUBIC
@ FLUID_DISPLAY_INTERP_LINEAR
@ FLUID_DOMAIN_USE_NOISE
@ FLUID_DOMAIN_ACTIVE_COLORS
@ FLUID_DOMAIN_ACTIVE_COLOR_SET
@ FLUID_DOMAIN_FIELD_PHI_OUT
@ FLUID_DOMAIN_FIELD_PHI_OBSTACLE
@ FLUID_DOMAIN_FIELD_FLAGS
@ FLUID_DOMAIN_FIELD_PHI
@ FLUID_DOMAIN_FIELD_PRESSURE
@ FLUID_DOMAIN_FIELD_PHI_IN
@ AXIS_SLICE_SINGLE
@ SLICE_AXIS_AUTO
eV3DShadingColorType
VolumeDisplayInterpMethod
@ VOLUME_DISPLAY_INTERP_CLOSEST
@ VOLUME_DISPLAY_INTERP_LINEAR
@ VOLUME_DISPLAY_INTERP_CUBIC
#define VOLUME_MATERIAL_NR
@ DRW_STATE_CULL_FRONT
Definition: DRW_render.h:317
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition: DRW_render.h:330
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
#define DRW_shgroup_call(shgroup, geom, ob)
Definition: DRW_render.h:414
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
struct GPUShader GPUShader
Definition: GPU_shader.h:20
GPUTexture * GPU_texture_create_1d(const char *name, int w, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:278
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:171
void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
Definition: gpu_texture.cc:688
@ 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
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
Scene scene
GPUBatch * DRW_cache_quad_get(void)
Definition: draw_cache.c:389
GPUBatch * DRW_cache_cube_get(void)
Definition: draw_cache.c:695
DRWVolumeGrid * DRW_volume_batch_cache_get_grid(struct Volume *volume, const struct VolumeGrid *grid)
void DRW_smoke_ensure_coba_field(struct FluidModifierData *fmd)
Definition: draw_fluid.c:427
void DRW_smoke_ensure(struct FluidModifierData *fmd, int highres)
Definition: draw_fluid.c:453
DefaultFramebufferList * DRW_viewport_framebuffer_list_get(void)
Definition: draw_manager.c:633
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:638
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float(*value)[4])
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_draw_pass(DRWPass *pass)
ccl_gpu_kernel_postfix ccl_global float int int int int sh
#define G(x, y, z)
float texture_to_object[4][4]
Definition: draw_cache.h:251
struct GPUTexture * texture
Definition: draw_cache.h:248
float object_to_texture[4][4]
Definition: draw_cache.h:252
struct GPUFrameBuffer * color_only_fb
struct GPUTexture * depth
struct GPUTexture * tex_density
struct GPUTexture * tex_color
struct GPUTexture * tex_field
struct MANTA * fluid
struct GPUTexture * tex_shadow
struct GPUTexture * tex_coba
struct GPUTexture * tex_flame
struct GPUTexture * tex_flame_coba
struct FluidDomainSettings * domain
float obmat[4][4]
void * data
VolumeDisplay display
WORKBENCH_PassList * psl
WORKBENCH_StorageList * stl
WORKBENCH_TextureList * txl
struct DRWPass * volume_ps
struct GPUUniformBuf * world_ubo
struct WORKBENCH_PrivateData * wpd
struct GPUTexture * dummy_coba_tx
struct GPUTexture * dummy_volume_tx
struct GPUTexture * dummy_shadow_tx
void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_UBO_Material *data, eV3DShadingColorType color_type)
eWORKBENCH_VolumeInterpType
@ WORKBENCH_VOLUME_INTERP_CUBIC
@ WORKBENCH_VOLUME_INTERP_LINEAR
@ WORKBENCH_VOLUME_INTERP_CLOSEST
GPUShader * workbench_shader_volume_get(bool slice, bool coba, eWORKBENCH_VolumeInterpType interp_type, bool smoke)
void workbench_volume_cache_init(WORKBENCH_Data *vedata)
void workbench_volume_draw_pass(WORKBENCH_Data *vedata)
static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata, Object *ob, ModifierData *md)
void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *UNUSED(scene), Object *ob, ModifierData *md, eV3DShadingColorType color_type)
static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd, Object *ob, eV3DShadingColorType color_type, float color[3])
static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata, Object *ob, eV3DShadingColorType color_type)
void workbench_volume_engine_init(WORKBENCH_Data *vedata)