625 lines
18 KiB
C
625 lines
18 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup gpu
|
|
*
|
|
* GPU fluid drawing functions.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "BLI_math.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "DNA_fluid_types.h"
|
|
#include "DNA_modifier_types.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BKE_colorband.h"
|
|
|
|
#include "GPU_texture.h"
|
|
|
|
#include "draw_common.h" /* Own include. */
|
|
|
|
#ifdef WITH_FLUID
|
|
# include "manta_fluid_API.h"
|
|
#endif
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Private API
|
|
* \{ */
|
|
|
|
#ifdef WITH_FLUID
|
|
|
|
enum {
|
|
TFUNC_FLAME_SPECTRUM = 0,
|
|
TFUNC_COLOR_RAMP = 1,
|
|
};
|
|
|
|
# define TFUNC_WIDTH 256
|
|
|
|
static void create_flame_spectrum_texture(float *data)
|
|
{
|
|
# define FIRE_THRESH 7
|
|
# define MAX_FIRE_ALPHA 0.06f
|
|
# define FULL_ON_FIRE 100
|
|
|
|
float *spec_pixels = (float *)MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float),
|
|
"spec_pixels");
|
|
|
|
blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
for (int j = 0; j < 16; j++) {
|
|
for (int k = 0; k < TFUNC_WIDTH; k++) {
|
|
int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
|
|
if (k >= FIRE_THRESH) {
|
|
spec_pixels[index] = (data[k * 4]);
|
|
spec_pixels[index + 1] = (data[k * 4 + 1]);
|
|
spec_pixels[index + 2] = (data[k * 4 + 2]);
|
|
spec_pixels[index + 3] = MAX_FIRE_ALPHA *
|
|
((k > FULL_ON_FIRE) ?
|
|
1.0f :
|
|
(k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
|
|
}
|
|
else {
|
|
zero_v4(&spec_pixels[index]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
|
|
|
|
MEM_freeN(spec_pixels);
|
|
|
|
# undef FIRE_THRESH
|
|
# undef MAX_FIRE_ALPHA
|
|
# undef FULL_ON_FIRE
|
|
}
|
|
|
|
static void create_color_ramp(const struct ColorBand *coba, float *data)
|
|
{
|
|
for (int i = 0; i < TFUNC_WIDTH; i++) {
|
|
BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
|
|
straight_to_premul_v4(&data[i * 4]);
|
|
}
|
|
}
|
|
|
|
static GPUTexture *create_transfer_function(int type, const struct ColorBand *coba)
|
|
{
|
|
float *data = (float *)MEM_mallocN(sizeof(float[4]) * TFUNC_WIDTH, __func__);
|
|
|
|
switch (type) {
|
|
case TFUNC_FLAME_SPECTRUM:
|
|
create_flame_spectrum_texture(data);
|
|
break;
|
|
case TFUNC_COLOR_RAMP:
|
|
create_color_ramp(coba, data);
|
|
break;
|
|
}
|
|
|
|
GPUTexture *tex = GPU_texture_create_1d("transf_func", TFUNC_WIDTH, 1, GPU_SRGB8_A8, data);
|
|
|
|
MEM_freeN(data);
|
|
|
|
return tex;
|
|
}
|
|
|
|
static void swizzle_texture_channel_single(GPUTexture *tex)
|
|
{
|
|
/* Swizzle texture channels so that we get useful RGBA values when sampling
|
|
* a texture with fewer channels, e.g. when using density as color. */
|
|
GPU_texture_swizzle_set(tex, "rrr1");
|
|
}
|
|
|
|
static float *rescale_3d(const int dim[3],
|
|
const int final_dim[3],
|
|
int channels,
|
|
const float *fpixels)
|
|
{
|
|
const uint w = dim[0], h = dim[1], d = dim[2];
|
|
const uint fw = final_dim[0], fh = final_dim[1], fd = final_dim[2];
|
|
const uint xf = w / fw, yf = h / fh, zf = d / fd;
|
|
const uint pixel_count = fw * fh * fd;
|
|
float *nfpixels = (float *)MEM_mallocN(channels * sizeof(float) * pixel_count, __func__);
|
|
|
|
if (nfpixels) {
|
|
printf("Performance: You need to scale a 3D texture, feel the pain!\n");
|
|
|
|
for (uint k = 0; k < fd; k++) {
|
|
for (uint j = 0; j < fh; j++) {
|
|
for (uint i = 0; i < fw; i++) {
|
|
/* Obviously doing nearest filtering here,
|
|
* it's going to be slow in any case, let's not make it worse. */
|
|
float xb = i * xf;
|
|
float yb = j * yf;
|
|
float zb = k * zf;
|
|
uint offset = k * (fw * fh) + i * fh + j;
|
|
uint offset_orig = (zb) * (w * h) + (xb)*h + (yb);
|
|
|
|
if (channels == 4) {
|
|
nfpixels[offset * 4] = fpixels[offset_orig * 4];
|
|
nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
|
|
nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
|
|
nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
|
|
}
|
|
else if (channels == 1) {
|
|
nfpixels[offset] = fpixels[offset_orig];
|
|
}
|
|
else {
|
|
BLI_assert(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nfpixels;
|
|
}
|
|
|
|
/* Will resize input to fit GL system limits. */
|
|
static GPUTexture *create_volume_texture(const int dim[3],
|
|
eGPUTextureFormat texture_format,
|
|
eGPUDataFormat data_format,
|
|
const void *data)
|
|
{
|
|
GPUTexture *tex = NULL;
|
|
int final_dim[3] = {UNPACK3(dim)};
|
|
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
while (1) {
|
|
tex = GPU_texture_create_3d(
|
|
"volume", UNPACK3(final_dim), 1, texture_format, data_format, NULL);
|
|
|
|
if (tex != NULL) {
|
|
break;
|
|
}
|
|
|
|
if (final_dim[0] == 1 && final_dim[1] == 1 && final_dim[2] == 1) {
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
final_dim[i] = max_ii(1, final_dim[i] / 2);
|
|
}
|
|
}
|
|
|
|
if (tex == NULL) {
|
|
printf("Error: Could not create 3D texture.\n");
|
|
tex = GPU_texture_create_error(3, false);
|
|
}
|
|
else if (equals_v3v3_int(dim, final_dim)) {
|
|
/* No need to resize, just upload the data. */
|
|
GPU_texture_update_sub(tex, data_format, data, 0, 0, 0, UNPACK3(final_dim));
|
|
}
|
|
else if (data_format != GPU_DATA_FLOAT) {
|
|
printf("Error: Could not allocate 3D texture and not attempting to rescale non-float data.\n");
|
|
tex = GPU_texture_create_error(3, false);
|
|
}
|
|
else {
|
|
/* We need to resize the input. */
|
|
int channels = (ELEM(texture_format, GPU_R8, GPU_R16F, GPU_R32F)) ? 1 : 4;
|
|
float *rescaled_data = rescale_3d(dim, final_dim, channels, data);
|
|
if (rescaled_data) {
|
|
GPU_texture_update_sub(tex, GPU_DATA_FLOAT, rescaled_data, 0, 0, 0, UNPACK3(final_dim));
|
|
MEM_freeN(rescaled_data);
|
|
}
|
|
else {
|
|
printf("Error: Could not allocate rescaled 3d texture!\n");
|
|
GPU_texture_free(tex);
|
|
tex = GPU_texture_create_error(3, false);
|
|
}
|
|
}
|
|
return tex;
|
|
}
|
|
|
|
static GPUTexture *create_field_texture(FluidDomainSettings *fds, bool single_precision)
|
|
{
|
|
void *field = NULL;
|
|
eGPUDataFormat data_format = GPU_DATA_FLOAT;
|
|
eGPUTextureFormat texture_format = GPU_R8;
|
|
|
|
if (single_precision) {
|
|
texture_format = GPU_R32F;
|
|
}
|
|
|
|
switch (fds->coba_field) {
|
|
case FLUID_DOMAIN_FIELD_DENSITY:
|
|
field = manta_smoke_get_density(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_HEAT:
|
|
field = manta_smoke_get_heat(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FUEL:
|
|
field = manta_smoke_get_fuel(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_REACT:
|
|
field = manta_smoke_get_react(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FLAME:
|
|
field = manta_smoke_get_flame(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_VELOCITY_X:
|
|
field = manta_get_velocity_x(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_VELOCITY_Y:
|
|
field = manta_get_velocity_y(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_VELOCITY_Z:
|
|
field = manta_get_velocity_z(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_COLOR_R:
|
|
field = manta_smoke_get_color_r(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_COLOR_G:
|
|
field = manta_smoke_get_color_g(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_COLOR_B:
|
|
field = manta_smoke_get_color_b(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FORCE_X:
|
|
field = manta_get_force_x(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FORCE_Y:
|
|
field = manta_get_force_y(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FORCE_Z:
|
|
field = manta_get_force_z(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_PHI:
|
|
field = manta_get_phi(fds->fluid);
|
|
texture_format = GPU_R16F;
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_PHI_IN:
|
|
field = manta_get_phi_in(fds->fluid);
|
|
texture_format = GPU_R16F;
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_PHI_OUT:
|
|
field = manta_get_phiout_in(fds->fluid);
|
|
texture_format = GPU_R16F;
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_PHI_OBSTACLE:
|
|
field = manta_get_phiobs_in(fds->fluid);
|
|
texture_format = GPU_R16F;
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_FLAGS:
|
|
field = manta_smoke_get_flags(fds->fluid);
|
|
data_format = GPU_DATA_INT;
|
|
texture_format = GPU_R8UI;
|
|
break;
|
|
case FLUID_DOMAIN_FIELD_PRESSURE:
|
|
field = manta_get_pressure(fds->fluid);
|
|
texture_format = GPU_R16F;
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
if (field == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
GPUTexture *tex = create_volume_texture(fds->res, texture_format, data_format, field);
|
|
swizzle_texture_channel_single(tex);
|
|
return tex;
|
|
}
|
|
|
|
static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres)
|
|
{
|
|
int *dim = (highres) ? fds->res_noise : fds->res;
|
|
|
|
float *data;
|
|
if (highres) {
|
|
data = manta_noise_get_density(fds->fluid);
|
|
}
|
|
else {
|
|
data = manta_smoke_get_density(fds->fluid);
|
|
}
|
|
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, data);
|
|
swizzle_texture_channel_single(tex);
|
|
return tex;
|
|
}
|
|
|
|
static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres)
|
|
{
|
|
const bool has_color = (highres) ? manta_noise_has_colors(fds->fluid) :
|
|
manta_smoke_has_colors(fds->fluid);
|
|
|
|
if (!has_color) {
|
|
return NULL;
|
|
}
|
|
|
|
int cell_count = (highres) ? manta_noise_get_cells(fds->fluid) : fds->total_cells;
|
|
int *dim = (highres) ? fds->res_noise : fds->res;
|
|
float *data = (float *)MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
|
|
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (highres) {
|
|
manta_noise_get_rgba(fds->fluid, data, 0);
|
|
}
|
|
else {
|
|
manta_smoke_get_rgba(fds->fluid, data, 0);
|
|
}
|
|
|
|
GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, GPU_DATA_FLOAT, data);
|
|
|
|
MEM_freeN(data);
|
|
|
|
return tex;
|
|
}
|
|
|
|
static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres)
|
|
{
|
|
float *source = NULL;
|
|
const bool has_fuel = (highres) ? manta_noise_has_fuel(fds->fluid) :
|
|
manta_smoke_has_fuel(fds->fluid);
|
|
int *dim = (highres) ? fds->res_noise : fds->res;
|
|
|
|
if (!has_fuel) {
|
|
return NULL;
|
|
}
|
|
|
|
if (highres) {
|
|
source = manta_noise_get_flame(fds->fluid);
|
|
}
|
|
else {
|
|
source = manta_smoke_get_flame(fds->fluid);
|
|
}
|
|
|
|
GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, source);
|
|
swizzle_texture_channel_single(tex);
|
|
return tex;
|
|
}
|
|
|
|
static bool get_smoke_velocity_field(FluidDomainSettings *fds,
|
|
float **r_velocity_x,
|
|
float **r_velocity_y,
|
|
float **r_velocity_z)
|
|
{
|
|
const char vector_field = fds->vector_field;
|
|
switch ((FLUID_DisplayVectorField)vector_field) {
|
|
case FLUID_DOMAIN_VECTOR_FIELD_VELOCITY:
|
|
*r_velocity_x = manta_get_velocity_x(fds->fluid);
|
|
*r_velocity_y = manta_get_velocity_y(fds->fluid);
|
|
*r_velocity_z = manta_get_velocity_z(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_VECTOR_FIELD_GUIDE_VELOCITY:
|
|
*r_velocity_x = manta_get_guide_velocity_x(fds->fluid);
|
|
*r_velocity_y = manta_get_guide_velocity_y(fds->fluid);
|
|
*r_velocity_z = manta_get_guide_velocity_z(fds->fluid);
|
|
break;
|
|
case FLUID_DOMAIN_VECTOR_FIELD_FORCE:
|
|
*r_velocity_x = manta_get_force_x(fds->fluid);
|
|
*r_velocity_y = manta_get_force_y(fds->fluid);
|
|
*r_velocity_z = manta_get_force_z(fds->fluid);
|
|
break;
|
|
}
|
|
|
|
return *r_velocity_x && *r_velocity_y && *r_velocity_z;
|
|
}
|
|
|
|
#endif /* WITH_FLUID */
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Public API
|
|
* \{ */
|
|
|
|
void DRW_smoke_free(FluidModifierData *fmd)
|
|
{
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
|
|
if (fmd->domain->tex_density) {
|
|
GPU_texture_free(fmd->domain->tex_density);
|
|
fmd->domain->tex_density = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_color) {
|
|
GPU_texture_free(fmd->domain->tex_color);
|
|
fmd->domain->tex_color = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_shadow) {
|
|
GPU_texture_free(fmd->domain->tex_shadow);
|
|
fmd->domain->tex_shadow = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_flame) {
|
|
GPU_texture_free(fmd->domain->tex_flame);
|
|
fmd->domain->tex_flame = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_flame_coba) {
|
|
GPU_texture_free(fmd->domain->tex_flame_coba);
|
|
fmd->domain->tex_flame_coba = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_coba) {
|
|
GPU_texture_free(fmd->domain->tex_coba);
|
|
fmd->domain->tex_coba = NULL;
|
|
}
|
|
|
|
if (fmd->domain->tex_field) {
|
|
GPU_texture_free(fmd->domain->tex_field);
|
|
fmd->domain->tex_field = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
|
|
{
|
|
#ifndef WITH_FLUID
|
|
UNUSED_VARS(fmd);
|
|
#else
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
|
FluidDomainSettings *fds = fmd->domain;
|
|
|
|
if (!fds->tex_field) {
|
|
fds->tex_field = create_field_texture(fds, false);
|
|
}
|
|
if (!fds->tex_coba && !ELEM(fds->coba_field,
|
|
FLUID_DOMAIN_FIELD_PHI,
|
|
FLUID_DOMAIN_FIELD_PHI_IN,
|
|
FLUID_DOMAIN_FIELD_PHI_OUT,
|
|
FLUID_DOMAIN_FIELD_PHI_OBSTACLE,
|
|
FLUID_DOMAIN_FIELD_FLAGS,
|
|
FLUID_DOMAIN_FIELD_PRESSURE)) {
|
|
fds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, fds->coba);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
|
|
{
|
|
#ifndef WITH_FLUID
|
|
UNUSED_VARS(fmd, highres);
|
|
#else
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
|
FluidDomainSettings *fds = fmd->domain;
|
|
|
|
if (!fds->tex_density) {
|
|
fds->tex_density = create_density_texture(fds, highres);
|
|
}
|
|
if (!fds->tex_color) {
|
|
fds->tex_color = create_color_texture(fds, highres);
|
|
}
|
|
if (!fds->tex_flame) {
|
|
fds->tex_flame = create_flame_texture(fds, highres);
|
|
}
|
|
if (!fds->tex_flame_coba && fds->tex_flame) {
|
|
fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
|
|
}
|
|
if (!fds->tex_shadow) {
|
|
fds->tex_shadow = create_volume_texture(
|
|
fds->res, GPU_R8, GPU_DATA_FLOAT, manta_smoke_get_shadow(fds->fluid));
|
|
}
|
|
}
|
|
#endif /* WITH_FLUID */
|
|
}
|
|
|
|
void DRW_smoke_ensure_velocity(FluidModifierData *fmd)
|
|
{
|
|
#ifndef WITH_FLUID
|
|
UNUSED_VARS(fmd);
|
|
#else
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
|
FluidDomainSettings *fds = fmd->domain;
|
|
float *vel_x = NULL, *vel_y = NULL, *vel_z = NULL;
|
|
|
|
if (!get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z)) {
|
|
fds->vector_field = FLUID_DOMAIN_VECTOR_FIELD_VELOCITY;
|
|
get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z);
|
|
}
|
|
|
|
if (ELEM(NULL, vel_x, vel_y, vel_z)) {
|
|
return;
|
|
}
|
|
|
|
if (!fds->tex_velocity_x) {
|
|
fds->tex_velocity_x = GPU_texture_create_3d(
|
|
"velx", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_x);
|
|
fds->tex_velocity_y = GPU_texture_create_3d(
|
|
"vely", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_y);
|
|
fds->tex_velocity_z = GPU_texture_create_3d(
|
|
"velz", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_z);
|
|
}
|
|
}
|
|
#endif /* WITH_FLUID */
|
|
}
|
|
|
|
void DRW_fluid_ensure_flags(FluidModifierData *fmd)
|
|
{
|
|
#ifndef WITH_FLUID
|
|
UNUSED_VARS(fmd);
|
|
#else
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
|
FluidDomainSettings *fds = fmd->domain;
|
|
if (!fds->tex_flags) {
|
|
fds->tex_flags = create_volume_texture(
|
|
fds->res, GPU_R8UI, GPU_DATA_INT, manta_smoke_get_flags(fds->fluid));
|
|
|
|
swizzle_texture_channel_single(fds->tex_flags);
|
|
}
|
|
}
|
|
#endif /* WITH_FLUID */
|
|
}
|
|
|
|
void DRW_fluid_ensure_range_field(FluidModifierData *fmd)
|
|
{
|
|
#ifndef WITH_FLUID
|
|
UNUSED_VARS(fmd);
|
|
#else
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
|
FluidDomainSettings *fds = fmd->domain;
|
|
|
|
if (!fds->tex_range_field) {
|
|
fds->tex_range_field = create_field_texture(fds, true);
|
|
}
|
|
}
|
|
#endif /* WITH_FLUID */
|
|
}
|
|
|
|
/* TODO Unify with the other GPU_free_smoke. */
|
|
void DRW_smoke_free_velocity(FluidModifierData *fmd)
|
|
{
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
|
|
if (fmd->domain->tex_velocity_x) {
|
|
GPU_texture_free(fmd->domain->tex_velocity_x);
|
|
}
|
|
|
|
if (fmd->domain->tex_velocity_y) {
|
|
GPU_texture_free(fmd->domain->tex_velocity_y);
|
|
}
|
|
|
|
if (fmd->domain->tex_velocity_z) {
|
|
GPU_texture_free(fmd->domain->tex_velocity_z);
|
|
}
|
|
|
|
if (fmd->domain->tex_flags) {
|
|
GPU_texture_free(fmd->domain->tex_flags);
|
|
}
|
|
|
|
if (fmd->domain->tex_range_field) {
|
|
GPU_texture_free(fmd->domain->tex_range_field);
|
|
}
|
|
|
|
fmd->domain->tex_velocity_x = NULL;
|
|
fmd->domain->tex_velocity_y = NULL;
|
|
fmd->domain->tex_velocity_z = NULL;
|
|
fmd->domain->tex_flags = NULL;
|
|
fmd->domain->tex_range_field = NULL;
|
|
}
|
|
}
|
|
|
|
/** \} */
|