Blender V4.5
draw_fluid.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstring>
12
13#include "BLI_listbase.h"
14#include "BLI_utildefines.h"
15
16#include "DNA_fluid_types.h"
17#include "DNA_modifier_types.h"
18
19#include "MEM_guardedalloc.h"
20
21#include "BKE_colorband.hh"
22
24
25#include "GPU_texture.hh"
26
28
29#include "draw_common_c.hh" /* Own include. */
30
31#ifdef WITH_FLUID
32# include "manta_fluid_API.h"
33#endif
34
35/* -------------------------------------------------------------------- */
38
39#ifdef WITH_FLUID
40
41enum {
42 TFUNC_FLAME_SPECTRUM = 0,
43 TFUNC_COLOR_RAMP = 1,
44};
45
46# define TFUNC_WIDTH 256
47
48static void create_flame_spectrum_texture(float *data)
49{
50# define FIRE_THRESH 7
51# define MAX_FIRE_ALPHA 0.06f
52# define FULL_ON_FIRE 100
53
54 float *spec_pixels = MEM_malloc_arrayN<float>(TFUNC_WIDTH * 4 * 16 * 16, "spec_pixels");
55
57
58 for (int i = 0; i < 16; i++) {
59 for (int j = 0; j < 16; j++) {
60 for (int k = 0; k < TFUNC_WIDTH; k++) {
61 int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
62 if (k >= FIRE_THRESH) {
63 spec_pixels[index] = (data[k * 4]);
64 spec_pixels[index + 1] = (data[k * 4 + 1]);
65 spec_pixels[index + 2] = (data[k * 4 + 2]);
66 spec_pixels[index + 3] = MAX_FIRE_ALPHA *
67 ((k > FULL_ON_FIRE) ?
68 1.0f :
69 (k - FIRE_THRESH) / (float(FULL_ON_FIRE) - FIRE_THRESH));
70 }
71 else {
72 zero_v4(&spec_pixels[index]);
73 }
74 }
75 }
76 }
77
78 memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
79
80 MEM_freeN(spec_pixels);
81
82# undef FIRE_THRESH
83# undef MAX_FIRE_ALPHA
84# undef FULL_ON_FIRE
85}
86
87static void create_color_ramp(const ColorBand *coba, float *data)
88{
89 for (int i = 0; i < TFUNC_WIDTH; i++) {
90 BKE_colorband_evaluate(coba, float(i) / TFUNC_WIDTH, &data[i * 4]);
92 }
93}
94
95static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
96{
97 float *data = (float *)MEM_mallocN(sizeof(float[4]) * TFUNC_WIDTH, __func__);
98
99 switch (type) {
100 case TFUNC_FLAME_SPECTRUM:
101 create_flame_spectrum_texture(data);
102 break;
103 case TFUNC_COLOR_RAMP:
104 create_color_ramp(coba, data);
105 break;
106 }
107
108 GPUTexture *tex = GPU_texture_create_1d(
109 "transf_func", TFUNC_WIDTH, 1, GPU_SRGB8_A8, GPU_TEXTURE_USAGE_SHADER_READ, data);
110
112
113 return tex;
114}
115
116static void swizzle_texture_channel_single(GPUTexture *tex)
117{
118 /* Swizzle texture channels so that we get useful RGBA values when sampling
119 * a texture with fewer channels, e.g. when using density as color. */
120 GPU_texture_swizzle_set(tex, "rrr1");
121}
122
123static float *rescale_3d(const int dim[3],
124 const int final_dim[3],
125 int channels,
126 const float *fpixels)
127{
128 const uint w = dim[0], h = dim[1], d = dim[2];
129 const uint fw = final_dim[0], fh = final_dim[1], fd = final_dim[2];
130 const uint xf = w / fw, yf = h / fh, zf = d / fd;
131 const uint pixel_count = fw * fh * fd;
132 float *nfpixels = (float *)MEM_mallocN(channels * sizeof(float) * pixel_count, __func__);
133
134 if (nfpixels) {
135 printf("Performance: You need to scale a 3D texture, feel the pain!\n");
136
137 for (uint k = 0; k < fd; k++) {
138 for (uint j = 0; j < fh; j++) {
139 for (uint i = 0; i < fw; i++) {
140 /* Obviously doing nearest filtering here,
141 * it's going to be slow in any case, let's not make it worse. */
142 float xb = i * xf;
143 float yb = j * yf;
144 float zb = k * zf;
145 uint offset = k * (fw * fh) + i * fh + j;
146 uint offset_orig = (zb) * (w * h) + (xb)*h + (yb);
147
148 if (channels == 4) {
149 nfpixels[offset * 4] = fpixels[offset_orig * 4];
150 nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
151 nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
152 nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
153 }
154 else if (channels == 1) {
155 nfpixels[offset] = fpixels[offset_orig];
156 }
157 else {
158 BLI_assert(0);
159 }
160 }
161 }
162 }
163 }
164 return nfpixels;
165}
166
167/* Will resize input to fit GL system limits. */
168static GPUTexture *create_volume_texture(const int dim[3],
169 eGPUTextureFormat texture_format,
170 eGPUDataFormat data_format,
171 const void *data)
172{
173 GPUTexture *tex = nullptr;
174 blender::int3 final_dim = {UNPACK3(dim)};
175
176 if (data == nullptr) {
177 return nullptr;
178 }
179
180 while (true) {
182 "volume", UNPACK3(final_dim), 1, texture_format, GPU_TEXTURE_USAGE_SHADER_READ, nullptr);
183
184 if (tex != nullptr) {
185 break;
186 }
187
188 if (final_dim[0] == 1 && final_dim[1] == 1 && final_dim[2] == 1) {
189 break;
190 }
191
192 for (int i = 0; i < 3; i++) {
193 final_dim[i] = max_ii(1, final_dim[i] / 2);
194 }
195 }
196
197 if (tex == nullptr) {
198 printf("Error: Could not create 3D texture.\n");
199 tex = GPU_texture_create_error(3, false);
200 }
201 else if (blender::int3(dim) == final_dim) {
202 /* No need to resize, just upload the data. */
203 GPU_texture_update_sub(tex, data_format, data, 0, 0, 0, UNPACK3(final_dim));
204 }
205 else if (data_format != GPU_DATA_FLOAT) {
206 printf("Error: Could not allocate 3D texture and not attempting to rescale non-float data.\n");
207 tex = GPU_texture_create_error(3, false);
208 }
209 else {
210 /* We need to resize the input. */
211 int channels = ELEM(texture_format, GPU_R8, GPU_R16F, GPU_R32F) ? 1 : 4;
212 float *rescaled_data = rescale_3d(dim, final_dim, channels, static_cast<const float *>(data));
213 if (rescaled_data) {
214 GPU_texture_update_sub(tex, GPU_DATA_FLOAT, rescaled_data, 0, 0, 0, UNPACK3(final_dim));
215 MEM_freeN(rescaled_data);
216 }
217 else {
218 printf("Error: Could not allocate rescaled 3d texture!\n");
219 GPU_texture_free(tex);
220 tex = GPU_texture_create_error(3, false);
221 }
222 }
223 return tex;
224}
225
226static GPUTexture *create_field_texture(FluidDomainSettings *fds, bool single_precision)
227{
228 void *field = nullptr;
229 eGPUDataFormat data_format = GPU_DATA_FLOAT;
230 eGPUTextureFormat texture_format = GPU_R8;
231
232 if (single_precision) {
233 texture_format = GPU_R32F;
234 }
235
236 switch (fds->coba_field) {
238 field = manta_smoke_get_density(fds->fluid);
239 break;
241 field = manta_smoke_get_heat(fds->fluid);
242 break;
244 field = manta_smoke_get_fuel(fds->fluid);
245 break;
247 field = manta_smoke_get_react(fds->fluid);
248 break;
250 field = manta_smoke_get_flame(fds->fluid);
251 break;
253 field = manta_get_velocity_x(fds->fluid);
254 break;
256 field = manta_get_velocity_y(fds->fluid);
257 break;
259 field = manta_get_velocity_z(fds->fluid);
260 break;
262 field = manta_smoke_get_color_r(fds->fluid);
263 break;
265 field = manta_smoke_get_color_g(fds->fluid);
266 break;
268 field = manta_smoke_get_color_b(fds->fluid);
269 break;
271 field = manta_get_force_x(fds->fluid);
272 break;
274 field = manta_get_force_y(fds->fluid);
275 break;
277 field = manta_get_force_z(fds->fluid);
278 break;
280 field = manta_get_phi(fds->fluid);
281 texture_format = GPU_R16F;
282 break;
284 field = manta_get_phi_in(fds->fluid);
285 texture_format = GPU_R16F;
286 break;
288 field = manta_get_phiout_in(fds->fluid);
289 texture_format = GPU_R16F;
290 break;
292 field = manta_get_phiobs_in(fds->fluid);
293 texture_format = GPU_R16F;
294 break;
296 field = manta_smoke_get_flags(fds->fluid);
297 data_format = GPU_DATA_INT;
298 texture_format = GPU_R8UI;
299 break;
301 field = manta_get_pressure(fds->fluid);
302 texture_format = GPU_R16F;
303 break;
304 default:
305 return nullptr;
306 }
307
308 if (field == nullptr) {
309 return nullptr;
310 }
311
312 GPUTexture *tex = create_volume_texture(fds->res, texture_format, data_format, field);
313 swizzle_texture_channel_single(tex);
314 return tex;
315}
316
317static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres)
318{
319 int *dim = (highres) ? fds->res_noise : fds->res;
320
321 float *data;
322 if (highres) {
324 }
325 else {
327 }
328
329 if (data == nullptr) {
330 return nullptr;
331 }
332
333 GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, data);
334 swizzle_texture_channel_single(tex);
335 return tex;
336}
337
338static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres)
339{
340 const bool has_color = (highres) ? manta_noise_has_colors(fds->fluid) :
342
343 if (!has_color) {
344 return nullptr;
345 }
346
347 int cell_count = (highres) ? manta_noise_get_cells(fds->fluid) : fds->total_cells;
348 int *dim = (highres) ? fds->res_noise : fds->res;
349 float *data = MEM_calloc_arrayN<float>(cell_count * 4, "smokeColorTexture");
350
351 if (data == nullptr) {
352 return nullptr;
353 }
354
355 if (highres) {
357 }
358 else {
360 }
361
362 GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, GPU_DATA_FLOAT, data);
363
365
366 return tex;
367}
368
369static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres)
370{
371 float *source = nullptr;
372 const bool has_fuel = (highres) ? manta_noise_has_fuel(fds->fluid) :
374 int *dim = (highres) ? fds->res_noise : fds->res;
375
376 if (!has_fuel) {
377 return nullptr;
378 }
379
380 if (highres) {
381 source = manta_noise_get_flame(fds->fluid);
382 }
383 else {
384 source = manta_smoke_get_flame(fds->fluid);
385 }
386
387 GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, source);
388 swizzle_texture_channel_single(tex);
389 return tex;
390}
391
392static bool get_smoke_velocity_field(FluidDomainSettings *fds,
393 float **r_velocity_x,
394 float **r_velocity_y,
395 float **r_velocity_z)
396{
397 const char vector_field = fds->vector_field;
398 switch ((FLUID_DisplayVectorField)vector_field) {
400 *r_velocity_x = manta_get_velocity_x(fds->fluid);
401 *r_velocity_y = manta_get_velocity_y(fds->fluid);
402 *r_velocity_z = manta_get_velocity_z(fds->fluid);
403 break;
405 *r_velocity_x = manta_get_guide_velocity_x(fds->fluid);
406 *r_velocity_y = manta_get_guide_velocity_y(fds->fluid);
407 *r_velocity_z = manta_get_guide_velocity_z(fds->fluid);
408 break;
410 *r_velocity_x = manta_get_force_x(fds->fluid);
411 *r_velocity_y = manta_get_force_y(fds->fluid);
412 *r_velocity_z = manta_get_force_z(fds->fluid);
413 break;
414 }
415
416 return *r_velocity_x && *r_velocity_y && *r_velocity_z;
417}
418
419#endif /* WITH_FLUID */
420
422
423/* -------------------------------------------------------------------- */
426
428{
429#ifndef WITH_FLUID
430 UNUSED_VARS(fmd);
431#else
432 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
433 FluidDomainSettings *fds = fmd->domain;
434
435 if (!fds->tex_field) {
436 fds->tex_field = create_field_texture(fds, false);
437 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_field));
438 }
439 if (!fds->tex_coba && !ELEM(fds->coba_field,
446 {
447 fds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, fds->coba);
448 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_coba));
449 }
450 }
451#endif
452}
453
454void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
455{
456#ifndef WITH_FLUID
457 UNUSED_VARS(fmd, highres);
458#else
459 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
460 FluidDomainSettings *fds = fmd->domain;
461
462 if (!fds->tex_density) {
463 fds->tex_density = create_density_texture(fds, highres);
464 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_density));
465 }
466 if (!fds->tex_color) {
467 fds->tex_color = create_color_texture(fds, highres);
468 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_color));
469 }
470 if (!fds->tex_flame) {
471 fds->tex_flame = create_flame_texture(fds, highres);
472 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_flame));
473 }
474 if (!fds->tex_flame_coba && fds->tex_flame) {
475 fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, nullptr);
476 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_flame_coba));
477 }
478 if (!fds->tex_shadow) {
479 fds->tex_shadow = create_volume_texture(
481 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_shadow));
482 }
483 }
484#endif /* WITH_FLUID */
485}
486
488{
489#ifndef WITH_FLUID
490 UNUSED_VARS(fmd);
491#else
492 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
493 FluidDomainSettings *fds = fmd->domain;
494 float *vel_x = nullptr, *vel_y = nullptr, *vel_z = nullptr;
495
496 if (!get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z)) {
498 get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z);
499 }
500
501 if (ELEM(nullptr, vel_x, vel_y, vel_z)) {
502 return;
503 }
504
505 if (!fds->tex_velocity_x) {
507 "velx", UNPACK3(fds->res), 1, GPU_R16F, GPU_TEXTURE_USAGE_SHADER_READ, vel_x);
509 "vely", UNPACK3(fds->res), 1, GPU_R16F, GPU_TEXTURE_USAGE_SHADER_READ, vel_y);
511 "velz", UNPACK3(fds->res), 1, GPU_R16F, GPU_TEXTURE_USAGE_SHADER_READ, vel_z);
512 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_x));
513 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_y));
514 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_velocity_z));
515 }
516 }
517#endif /* WITH_FLUID */
518}
519
521{
522#ifndef WITH_FLUID
523 UNUSED_VARS(fmd);
524#else
525 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
526 FluidDomainSettings *fds = fmd->domain;
527 if (!fds->tex_flags) {
528 fds->tex_flags = create_volume_texture(
530 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_flags));
531
532 swizzle_texture_channel_single(fds->tex_flags);
533 }
534 }
535#endif /* WITH_FLUID */
536}
537
539{
540#ifndef WITH_FLUID
541 UNUSED_VARS(fmd);
542#else
543 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
544 FluidDomainSettings *fds = fmd->domain;
545
546 if (!fds->tex_range_field) {
547 fds->tex_range_field = create_field_texture(fds, true);
548 BLI_addtail(&drw_get().data->smoke_textures, BLI_genericNodeN(&fds->tex_range_field));
549 }
550 }
551#endif /* WITH_FLUID */
552}
553
555{
557}
558
559void DRW_smoke_exit(DRWData *drw_data)
560{
561 /* Free Smoke Textures after rendering */
562 /* XXX This is a waste of processing and GPU bandwidth if nothing
563 * is updated. But the problem is since Textures are stored in the
564 * modifier we don't want them to take precious VRAM if the
565 * modifier is not used for display. We should share them for
566 * all viewport in a redraw at least. */
567 LISTBASE_FOREACH (LinkData *, link, &drw_data->smoke_textures) {
568 GPU_TEXTURE_FREE_SAFE(*(GPUTexture **)link->data);
569 }
570 BLI_freelistN(&drw_data->smoke_textures);
571}
572
bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
Definition colorband.cc:395
#define BLI_assert(a)
Definition BLI_assert.h:46
LinkData * BLI_genericNodeN(void *data)
Definition listbase.cc:922
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE int max_ii(int a, int b)
MINLINE void straight_to_premul_v4(float color[4])
MINLINE void zero_v4(float r[4])
unsigned int uint
#define UNUSED_VARS(...)
#define UNPACK3(a)
#define ELEM(...)
@ FLUID_DOMAIN_FIELD_COLOR_B
@ FLUID_DOMAIN_FIELD_FLAME
@ FLUID_DOMAIN_FIELD_REACT
@ FLUID_DOMAIN_FIELD_PHI_OUT
@ FLUID_DOMAIN_FIELD_FORCE_Z
@ FLUID_DOMAIN_FIELD_PHI_OBSTACLE
@ FLUID_DOMAIN_FIELD_FLAGS
@ FLUID_DOMAIN_FIELD_VELOCITY_Z
@ FLUID_DOMAIN_FIELD_FORCE_Y
@ FLUID_DOMAIN_FIELD_PHI
@ FLUID_DOMAIN_FIELD_PRESSURE
@ FLUID_DOMAIN_FIELD_VELOCITY_X
@ FLUID_DOMAIN_FIELD_DENSITY
@ FLUID_DOMAIN_FIELD_VELOCITY_Y
@ FLUID_DOMAIN_FIELD_PHI_IN
@ FLUID_DOMAIN_FIELD_HEAT
@ FLUID_DOMAIN_FIELD_COLOR_G
@ FLUID_DOMAIN_FIELD_FORCE_X
@ FLUID_DOMAIN_FIELD_FUEL
@ FLUID_DOMAIN_FIELD_COLOR_R
FLUID_DisplayVectorField
@ FLUID_DOMAIN_VECTOR_FIELD_FORCE
@ FLUID_DOMAIN_VECTOR_FIELD_VELOCITY
@ FLUID_DOMAIN_VECTOR_FIELD_GUIDE_VELOCITY
@ MOD_FLUID_TYPE_DOMAIN
GPUTexture * GPU_texture_create_1d(const char *name, int width, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
GPUTexture * GPU_texture_create_error(int dimension, bool array)
eGPUDataFormat
@ GPU_DATA_INT
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_SHADER_READ
void GPU_texture_update_sub(GPUTexture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
GPUTexture * GPU_texture_create_3d(const char *name, int width, int height, int depth, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const void *data)
#define GPU_TEXTURE_FREE_SAFE(texture)
eGPUTextureFormat
@ GPU_R32F
@ GPU_SRGB8_A8
@ GPU_R16F
@ GPU_R8UI
@ GPU_R8
@ GPU_RGBA8
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4])
void IMB_colormanagement_blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max)
Read Guarded memory(de)allocation.
BMesh const char void * data
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
DRWContext & drw_get()
void DRW_fluid_ensure_flags(FluidModifierData *fmd)
void DRW_smoke_begin_sync(DRWData *drw_data)
void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
void DRW_fluid_ensure_range_field(FluidModifierData *fmd)
void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
void DRW_smoke_ensure_velocity(FluidModifierData *fmd)
void DRW_smoke_exit(DRWData *drw_data)
#define printf(...)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
float * manta_noise_get_density(struct MANTA *smoke)
float * manta_smoke_get_color_r(struct MANTA *smoke)
float * manta_smoke_get_shadow(struct MANTA *smoke)
float * manta_get_force_z(struct MANTA *fluid)
bool manta_noise_has_colors(struct MANTA *smoke)
float * manta_get_force_y(struct MANTA *fluid)
float * manta_get_guide_velocity_y(struct MANTA *fluid)
float * manta_smoke_get_react(struct MANTA *smoke)
float * manta_get_guide_velocity_z(struct MANTA *fluid)
float * manta_get_guide_velocity_x(struct MANTA *fluid)
void manta_noise_get_rgba(struct MANTA *smoke, float *data, int sequential)
float * manta_get_velocity_y(struct MANTA *fluid)
bool manta_noise_has_fuel(struct MANTA *smoke)
float * manta_get_force_x(struct MANTA *fluid)
float * manta_smoke_get_density(struct MANTA *smoke)
float * manta_get_phi(struct MANTA *fluid)
float * manta_get_phi_in(struct MANTA *fluid)
float * manta_get_velocity_z(struct MANTA *fluid)
bool manta_smoke_has_colors(struct MANTA *smoke)
float * manta_get_phiout_in(struct MANTA *fluid)
float * manta_get_phiobs_in(struct MANTA *fluid)
int * manta_smoke_get_flags(struct MANTA *smoke)
float * manta_get_velocity_x(struct MANTA *fluid)
bool manta_smoke_has_fuel(struct MANTA *smoke)
float * manta_get_pressure(struct MANTA *fluid)
float * manta_smoke_get_color_g(struct MANTA *smoke)
int manta_noise_get_cells(struct MANTA *smoke)
float * manta_smoke_get_heat(struct MANTA *smoke)
float * manta_smoke_get_color_b(struct MANTA *smoke)
void manta_smoke_get_rgba(struct MANTA *smoke, float *data, int sequential)
float * manta_smoke_get_fuel(struct MANTA *smoke)
float * manta_smoke_get_flame(struct MANTA *smoke)
float * manta_noise_get_flame(struct MANTA *smoke)
VecBase< int32_t, 3 > int3
ListBase smoke_textures
struct GPUTexture * tex_density
struct GPUTexture * tex_range_field
struct GPUTexture * tex_velocity_x
struct GPUTexture * tex_color
struct GPUTexture * tex_velocity_y
struct GPUTexture * tex_field
struct GPUTexture * tex_velocity_z
struct GPUTexture * tex_shadow
struct ColorBand * coba
struct GPUTexture * tex_flags
struct GPUTexture * tex_coba
struct GPUTexture * tex_flame
struct GPUTexture * tex_flame_coba
struct FluidDomainSettings * domain
i
Definition text_draw.cc:230