Viewport smoke: add support to render the volume using a color ramp.
This is yet another debug option that allows to render an arbitrary simulation field by using a color ramp to inspect its voxel values. Note that when using this, fire rendering is turned off. Reviewers: plasmasolutions, gottfried Differential Revision: https://developer.blender.org/D1733
This commit is contained in:
parent
4e68f48227
commit
b6d35e1fa7
|
@ -397,6 +397,14 @@ class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel):
|
|||
col.prop(domain, "vector_draw_type")
|
||||
col.prop(domain, "vector_scale")
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Color Mapping:")
|
||||
layout.prop(domain, "use_color_ramp")
|
||||
col = layout.column();
|
||||
col.enabled = domain.use_color_ramp
|
||||
col.prop(domain, "coba_field")
|
||||
col.template_color_ramp(domain, "color_ramp", expand=True)
|
||||
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
|
|
@ -360,6 +360,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
|
|||
BKE_ptcache_free_list(&(smd->domain->ptcaches[0]));
|
||||
smd->domain->point_cache[0] = NULL;
|
||||
|
||||
if (smd->domain->coba) {
|
||||
MEM_freeN(smd->domain->coba);
|
||||
}
|
||||
|
||||
MEM_freeN(smd->domain);
|
||||
smd->domain = NULL;
|
||||
}
|
||||
|
@ -544,6 +548,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
|||
smd->domain->slice_depth = 0.5f;
|
||||
smd->domain->slice_axis = 0;
|
||||
smd->domain->vector_scale = 1.0f;
|
||||
|
||||
smd->domain->coba = NULL;
|
||||
smd->domain->coba_field = FLUID_FIELD_DENSITY;
|
||||
}
|
||||
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
|
||||
{
|
||||
|
@ -646,6 +653,10 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
|
|||
tsmd->domain->draw_velocity = smd->domain->draw_velocity;
|
||||
tsmd->domain->vector_draw_type = smd->domain->vector_draw_type;
|
||||
tsmd->domain->vector_scale = smd->domain->vector_scale;
|
||||
|
||||
if (smd->domain->coba) {
|
||||
tsmd->domain->coba = MEM_dupallocN(smd->domain->coba);
|
||||
}
|
||||
}
|
||||
else if (tsmd->flow) {
|
||||
tsmd->flow->psys = smd->flow->psys;
|
||||
|
|
|
@ -5091,6 +5091,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
|||
smd->domain->tex = NULL;
|
||||
smd->domain->tex_shadow = NULL;
|
||||
smd->domain->tex_wt = NULL;
|
||||
smd->domain->coba = newdataadr(fd, smd->domain->coba);
|
||||
|
||||
smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights);
|
||||
if (!smd->domain->effector_weights)
|
||||
|
|
|
@ -1728,6 +1728,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
|
|||
smd->domain->point_cache[1]->step = 1;
|
||||
|
||||
write_pointcaches(wd, &(smd->domain->ptcaches[1]));
|
||||
|
||||
if (smd->domain->coba) {
|
||||
writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
|
||||
}
|
||||
}
|
||||
|
||||
writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
|
||||
|
|
|
@ -7915,10 +7915,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
|
|||
if (!render_override && sds->draw_velocity) {
|
||||
draw_smoke_velocity(sds, viewnormal);
|
||||
}
|
||||
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
draw_smoke_heat(smd->domain, ob);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -41,6 +41,7 @@
|
|||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_texture.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
#include "smoke_API.h"
|
||||
|
@ -62,28 +63,33 @@ struct GPUTexture;
|
|||
# include "PIL_time_utildefines.h"
|
||||
#endif
|
||||
|
||||
static GPUTexture *create_flame_spectrum_texture(void)
|
||||
/* *************************** Transfer functions *************************** */
|
||||
|
||||
enum {
|
||||
TFUNC_FLAME_SPECTRUM = 0,
|
||||
TFUNC_COLOR_RAMP = 1,
|
||||
};
|
||||
|
||||
#define TFUNC_WIDTH 256
|
||||
|
||||
static void create_flame_spectrum_texture(float *data)
|
||||
{
|
||||
#define SPEC_WIDTH 256
|
||||
#define FIRE_THRESH 7
|
||||
#define MAX_FIRE_ALPHA 0.06f
|
||||
#define FULL_ON_FIRE 100
|
||||
|
||||
GPUTexture *tex;
|
||||
int i, j, k;
|
||||
float *spec_data = MEM_mallocN(SPEC_WIDTH * 4 * sizeof(float), "spec_data");
|
||||
float *spec_pixels = MEM_mallocN(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
|
||||
float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
|
||||
|
||||
blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000);
|
||||
blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (k = 0; k < SPEC_WIDTH; k++) {
|
||||
int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
|
||||
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] = (spec_data[k * 4]);
|
||||
spec_pixels[index + 1] = (spec_data[k * 4 + 1]);
|
||||
spec_pixels[index + 2] = (spec_data[k * 4 + 2]);
|
||||
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));
|
||||
}
|
||||
|
@ -94,19 +100,69 @@ static GPUTexture *create_flame_spectrum_texture(void)
|
|||
}
|
||||
}
|
||||
|
||||
tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
|
||||
memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
|
||||
|
||||
MEM_freeN(spec_data);
|
||||
MEM_freeN(spec_pixels);
|
||||
|
||||
#undef SPEC_WIDTH
|
||||
#undef FIRE_THRESH
|
||||
#undef MAX_FIRE_ALPHA
|
||||
#undef FULL_ON_FIRE
|
||||
}
|
||||
|
||||
static void create_color_ramp(const ColorBand *coba, float *data)
|
||||
{
|
||||
for (int i = 0; i < TFUNC_WIDTH; i++) {
|
||||
do_colorband(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
|
||||
{
|
||||
float *data = 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(TFUNC_WIDTH, data, NULL);
|
||||
|
||||
MEM_freeN(data);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
|
||||
{
|
||||
float *field = NULL;
|
||||
|
||||
switch (sds->coba_field) {
|
||||
#ifdef WITH_SMOKE
|
||||
case FLUID_FIELD_DENSITY: field = smoke_get_density(sds->fluid); break;
|
||||
case FLUID_FIELD_HEAT: field = smoke_get_heat(sds->fluid); break;
|
||||
case FLUID_FIELD_FUEL: field = smoke_get_fuel(sds->fluid); break;
|
||||
case FLUID_FIELD_REACT: field = smoke_get_react(sds->fluid); break;
|
||||
case FLUID_FIELD_FLAME: field = smoke_get_flame(sds->fluid); break;
|
||||
case FLUID_FIELD_VELOCITY_X: field = smoke_get_velocity_x(sds->fluid); break;
|
||||
case FLUID_FIELD_VELOCITY_Y: field = smoke_get_velocity_y(sds->fluid); break;
|
||||
case FLUID_FIELD_VELOCITY_Z: field = smoke_get_velocity_z(sds->fluid); break;
|
||||
case FLUID_FIELD_COLOR_R: field = smoke_get_color_r(sds->fluid); break;
|
||||
case FLUID_FIELD_COLOR_G: field = smoke_get_color_g(sds->fluid); break;
|
||||
case FLUID_FIELD_COLOR_B: field = smoke_get_color_b(sds->fluid); break;
|
||||
case FLUID_FIELD_FORCE_X: field = smoke_get_force_x(sds->fluid); break;
|
||||
case FLUID_FIELD_FORCE_Y: field = smoke_get_force_y(sds->fluid); break;
|
||||
case FLUID_FIELD_FORCE_Z: field = smoke_get_force_z(sds->fluid); break;
|
||||
#endif
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field);
|
||||
}
|
||||
|
||||
typedef struct VolumeSlicer {
|
||||
float size[3];
|
||||
float min[3];
|
||||
|
@ -347,6 +403,7 @@ static int create_view_aligned_slices(VolumeSlicer *slicer,
|
|||
}
|
||||
|
||||
static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture *tex_spec,
|
||||
GPUTexture *tex_tfunc, GPUTexture *tex_coba,
|
||||
bool use_fire, const float min[3],
|
||||
const float ob_sizei[3], const float invsize[3])
|
||||
{
|
||||
|
@ -359,6 +416,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
|
|||
int densityscale_location;
|
||||
int spec_location, flame_location;
|
||||
int shadow_location, actcol_location;
|
||||
int tfunc_location = 0;
|
||||
int coba_location = 0;
|
||||
|
||||
if (use_fire) {
|
||||
spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
|
||||
|
@ -370,6 +429,11 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
|
|||
soot_location = GPU_shader_get_uniform(shader, "soot_texture");
|
||||
stepsize_location = GPU_shader_get_uniform(shader, "step_size");
|
||||
densityscale_location = GPU_shader_get_uniform(shader, "density_scale");
|
||||
|
||||
if (sds->use_coba) {
|
||||
tfunc_location = GPU_shader_get_uniform(shader, "transfer_texture");
|
||||
coba_location = GPU_shader_get_uniform(shader, "color_band_texture");
|
||||
}
|
||||
}
|
||||
|
||||
GPU_shader_bind(shader);
|
||||
|
@ -397,6 +461,14 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
|
|||
if ((sds->active_fields & SM_ACTIVE_COLORS) == 0)
|
||||
mul_v3_v3(active_color, sds->active_color);
|
||||
GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color);
|
||||
|
||||
if (sds->use_coba) {
|
||||
GPU_texture_bind(tex_tfunc, 4);
|
||||
GPU_shader_uniform_texture(shader, tfunc_location, tex_tfunc);
|
||||
|
||||
GPU_texture_bind(tex_coba, 5);
|
||||
GPU_shader_uniform_texture(shader, coba_location, tex_coba);
|
||||
}
|
||||
}
|
||||
|
||||
GPU_shader_uniform_vector(shader, min_location, 3, 1, min);
|
||||
|
@ -404,7 +476,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
|
|||
GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize);
|
||||
}
|
||||
|
||||
static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire)
|
||||
static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec,
|
||||
GPUTexture *tex_tfunc, GPUTexture *tex_coba, bool use_fire)
|
||||
{
|
||||
GPU_shader_unbind();
|
||||
|
||||
|
@ -417,20 +490,30 @@ static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool u
|
|||
}
|
||||
else {
|
||||
GPU_texture_unbind(sds->tex_shadow);
|
||||
|
||||
if (sds->use_coba) {
|
||||
GPU_texture_unbind(tex_tfunc);
|
||||
GPU_texture_free(tex_tfunc);
|
||||
|
||||
GPU_texture_unbind(tex_coba);
|
||||
GPU_texture_free(tex_coba);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const VolumeSlicer *slicer,
|
||||
const float ob_sizei[3], const float invsize[3], const int num_points, const bool do_fire)
|
||||
{
|
||||
GPUTexture *tex_spec = (do_fire) ? create_flame_spectrum_texture() : NULL;
|
||||
GPUTexture *tex_spec = (do_fire) ? create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL) : NULL;
|
||||
GPUTexture *tex_tfunc = (sds->use_coba) ? create_transfer_function(TFUNC_COLOR_RAMP, sds->coba) : NULL;
|
||||
GPUTexture *tex_coba = (sds->use_coba) ? create_field_texture(sds) : NULL;
|
||||
|
||||
GLuint vertex_buffer;
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer->verts[0][0], GL_STATIC_DRAW);
|
||||
|
||||
bind_shader(sds, shader, tex_spec, do_fire, slicer->min, ob_sizei, invsize);
|
||||
bind_shader(sds, shader, tex_spec, tex_tfunc, tex_coba, do_fire, slicer->min, ob_sizei, invsize);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
|
@ -439,7 +522,7 @@ static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const Volum
|
|||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
unbind_shader(sds, tex_spec, do_fire);
|
||||
unbind_shader(sds, tex_spec, tex_tfunc, tex_coba, do_fire);
|
||||
|
||||
/* cleanup */
|
||||
|
||||
|
@ -459,7 +542,16 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
|
|||
|
||||
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame;
|
||||
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE);
|
||||
GPUBuiltinShader builtin_shader;
|
||||
|
||||
if (sds->use_coba) {
|
||||
builtin_shader = GPU_SHADER_SMOKE_COBA;
|
||||
}
|
||||
else {
|
||||
builtin_shader = GPU_SHADER_SMOKE;
|
||||
}
|
||||
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(builtin_shader);
|
||||
|
||||
if (!shader) {
|
||||
fprintf(stderr, "Unable to create GLSL smoke shader.\n");
|
||||
|
@ -549,7 +641,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
|
|||
draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false);
|
||||
|
||||
/* Draw fire separately (T47639). */
|
||||
if (use_fire) {
|
||||
if (use_fire && !sds->use_coba) {
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
draw_buffer(sds, fire_shader, &slicer, ob_sizei, invsize, num_points, true);
|
||||
}
|
||||
|
@ -759,50 +851,3 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
|
|||
UNUSED_VARS(domain, viewnormal);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
|
||||
{
|
||||
float x, y, z;
|
||||
float x0, y0, z0;
|
||||
int *base_res = domain->base_res;
|
||||
int *res = domain->res;
|
||||
int *res_min = domain->res_min;
|
||||
int *res_max = domain->res_max;
|
||||
float *heat = smoke_get_heat(domain->fluid);
|
||||
|
||||
float min[3];
|
||||
float *cell_size = domain->cell_size;
|
||||
float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
|
||||
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
|
||||
|
||||
/* set first position so that it doesn't jump when domain moves */
|
||||
x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
|
||||
y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
|
||||
z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
|
||||
if (x0 < res_min[0]) x0 += step_size;
|
||||
if (y0 < res_min[1]) y0 += step_size;
|
||||
if (z0 < res_min[2]) z0 += step_size;
|
||||
add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
|
||||
|
||||
for (x = floor(x0); x < res_max[0]; x += step_size)
|
||||
for (y = floor(y0); y < res_max[1]; y += step_size)
|
||||
for (z = floor(z0); z < res_max[2]; z += step_size) {
|
||||
int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
|
||||
|
||||
float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]};
|
||||
|
||||
/* draw heat as different sized points */
|
||||
if (heat[index] >= 0.01f) {
|
||||
float col_gb = 1.0f - heat[index];
|
||||
CLAMP(col_gb, 0.0f, 1.0f);
|
||||
glColor3f(1.0f, col_gb, col_gb);
|
||||
glPointSize(24.0f * heat[index]);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3f(pos[0], pos[1], pos[2]);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -296,14 +296,8 @@ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
|
|||
const float min[3], const float max[3],
|
||||
const float viewnormal[3]);
|
||||
|
||||
//#define SMOKE_DEBUG_HEAT
|
||||
|
||||
void draw_smoke_velocity(struct SmokeDomainSettings *domain, float viewnormal[3]);
|
||||
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob);
|
||||
#endif
|
||||
|
||||
/* workaround for trivial but noticeable camera bug caused by imprecision
|
||||
* between view border calculation in 2D/3D space, workaround for bug [#28037].
|
||||
* without this define we get the old behavior which is to try and align them
|
||||
|
|
|
@ -89,6 +89,7 @@ typedef enum GPUBuiltinShader {
|
|||
GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
|
||||
GPU_SHADER_SMOKE = 2,
|
||||
GPU_SHADER_SMOKE_FIRE = 3,
|
||||
GPU_SHADER_SMOKE_COBA = 4,
|
||||
} GPUBuiltinShader;
|
||||
|
||||
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
|
||||
|
|
|
@ -68,6 +68,7 @@ static struct GPUShadersGlobal {
|
|||
GPUShader *sep_gaussian_blur;
|
||||
GPUShader *smoke;
|
||||
GPUShader *smoke_fire;
|
||||
GPUShader *smoke_coba;
|
||||
/* cache for shader fx. Those can exist in combinations so store them here */
|
||||
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
|
||||
} shaders;
|
||||
|
@ -623,6 +624,13 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
|||
NULL, NULL, NULL, 0, 0, 0);
|
||||
retval = GG.shaders.smoke_fire;
|
||||
break;
|
||||
case GPU_SHADER_SMOKE_COBA:
|
||||
if (!GG.shaders.smoke_coba)
|
||||
GG.shaders.smoke_coba = GPU_shader_create(
|
||||
datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
|
||||
NULL, NULL, "#define USE_COBA;\n", 0, 0, 0);
|
||||
retval = GG.shaders.smoke_coba;
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval == NULL)
|
||||
|
@ -734,6 +742,11 @@ void GPU_shader_free_builtin_shaders(void)
|
|||
GG.shaders.smoke_fire = NULL;
|
||||
}
|
||||
|
||||
if (GG.shaders.smoke_coba) {
|
||||
GPU_shader_free(GG.shaders.smoke_coba);
|
||||
GG.shaders.smoke_coba = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
|
||||
if (GG.shaders.fx_shaders[i]) {
|
||||
GPU_shader_free(GG.shaders.fx_shaders[i]);
|
||||
|
|
|
@ -8,10 +8,17 @@ uniform float density_scale;
|
|||
uniform sampler3D soot_texture;
|
||||
uniform sampler3D shadow_texture;
|
||||
|
||||
#ifdef USE_COBA
|
||||
uniform sampler1D transfer_texture;
|
||||
uniform sampler3D color_band_texture;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
/* compute color and density from volume texture */
|
||||
vec4 soot = texture3D(soot_texture, coords);
|
||||
|
||||
#ifndef USE_COBA
|
||||
vec3 soot_color;
|
||||
if (soot.a != 0) {
|
||||
soot_color = active_color * soot.rgb / soot.a;
|
||||
|
@ -31,6 +38,11 @@ void main()
|
|||
|
||||
/* premultiply alpha */
|
||||
vec4 color = vec4(soot_alpha * soot_color, soot_alpha);
|
||||
#else
|
||||
float color_band = texture3D(color_band_texture, coords).r;
|
||||
vec4 transfer_function = texture1D(transfer_texture, color_band);
|
||||
vec4 color = transfer_function * density_scale;
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,23 @@ enum {
|
|||
VECTOR_DRAW_STREAMLINE = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
FLUID_FIELD_DENSITY = 0,
|
||||
FLUID_FIELD_HEAT = 1,
|
||||
FLUID_FIELD_FUEL = 2,
|
||||
FLUID_FIELD_REACT = 3,
|
||||
FLUID_FIELD_FLAME = 4,
|
||||
FLUID_FIELD_VELOCITY_X = 5,
|
||||
FLUID_FIELD_VELOCITY_Y = 6,
|
||||
FLUID_FIELD_VELOCITY_Z = 7,
|
||||
FLUID_FIELD_COLOR_R = 8,
|
||||
FLUID_FIELD_COLOR_G = 9,
|
||||
FLUID_FIELD_COLOR_B = 10,
|
||||
FLUID_FIELD_FORCE_X = 11,
|
||||
FLUID_FIELD_FORCE_Y = 12,
|
||||
FLUID_FIELD_FORCE_Z = 13,
|
||||
};
|
||||
|
||||
/* cache compression */
|
||||
#define SM_CACHE_LIGHT 0
|
||||
#define SM_CACHE_HEAVY 1
|
||||
|
@ -193,9 +210,13 @@ typedef struct SmokeDomainSettings {
|
|||
float slice_per_voxel;
|
||||
float slice_depth;
|
||||
float display_thickness;
|
||||
|
||||
struct ColorBand *coba;
|
||||
float vector_scale;
|
||||
char vector_draw_type;
|
||||
char pad2[3];
|
||||
char use_coba;
|
||||
char coba_field; /* simulation field used for the color mapping */
|
||||
char pad2;
|
||||
} SmokeDomainSettings;
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <limits.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "smoke_API.h"
|
||||
|
||||
|
@ -383,6 +385,17 @@ static void rna_SmokeFlow_uvlayer_set(PointerRNA *ptr, const char *value)
|
|||
rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name));
|
||||
}
|
||||
|
||||
static void rna_Smoke_use_color_ramp_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
|
||||
|
||||
sds->use_coba = value;
|
||||
|
||||
if (value && sds->coba == NULL) {
|
||||
sds->coba = add_colorband(false);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
|
@ -805,6 +818,41 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
|||
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Scale", "Multiplier for scaling the vectors");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
/* --------- Color mapping. --------- */
|
||||
|
||||
prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "use_coba", 0);
|
||||
RNA_def_property_boolean_funcs(prop, NULL, "rna_Smoke_use_color_ramp_set");
|
||||
RNA_def_property_ui_text(prop, "Use Color Ramp",
|
||||
"Render a simulation field while mapping its voxels values to the colors of a ramp");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
static EnumPropertyItem coba_field_items[] = {
|
||||
{FLUID_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"},
|
||||
{FLUID_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"},
|
||||
{FLUID_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"},
|
||||
{FLUID_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
|
||||
{FLUID_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"},
|
||||
{FLUID_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"},
|
||||
{FLUID_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"},
|
||||
{FLUID_FIELD_VELOCITY_X, "VELOCITY_X", 0, "X Velocity", "X component of the velocity field"},
|
||||
{FLUID_FIELD_VELOCITY_Y, "VELOCITY_Y", 0, "Y Velocity", "Y component of the velocity field"},
|
||||
{FLUID_FIELD_VELOCITY_Z, "VELOCITY_Z", 0, "Z Velocity", "Z component of the velocity field"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "coba_field");
|
||||
RNA_def_property_enum_items(prop, coba_field_items);
|
||||
RNA_def_property_ui_text(prop, "Field", "Simulation field to color map");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "coba");
|
||||
RNA_def_property_struct_type(prop, "ColorRamp");
|
||||
RNA_def_property_ui_text(prop, "Color Ramp", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue