diff options
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl | 9 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_volume.c | 14 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 112 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_smoke_types.h | 1 |
5 files changed, 134 insertions, 3 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 275d14dbca3..b63951b3eab 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5168,6 +5168,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) smd->domain->tex = NULL; smd->domain->tex_shadow = NULL; smd->domain->tex_flame = NULL; + smd->domain->tex_flame_coba = NULL; smd->domain->tex_velocity_x = NULL; smd->domain->tex_velocity_y = NULL; smd->domain->tex_velocity_z = NULL; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index fb3fcd2a4b6..0860660d8da 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -6,8 +6,11 @@ uniform mat4 ModelMatrix; uniform vec3 OrcoTexCoFactors[2]; uniform sampler2D depthBuffer; + uniform sampler3D densityTexture; uniform sampler3D shadowTexture; +uniform sampler3D flameTexture; +uniform sampler1D flameColorTexture; uniform int samplesLen = 256; uniform float stepLength; /* Step length in local space. */ @@ -65,6 +68,10 @@ float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) { vec3 co = ls_pos * 0.5 + 0.5; + + float flame = texture(flameTexture, co).r; + vec4 emission = texture(flameColorTexture, flame); + float shadows = texture(shadowTexture, co).r; vec4 density = texture(densityTexture, co); /* rgb: color, a: density */ density.a *= densityScale; @@ -72,6 +79,8 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) scattering = density.rgb * density.a; extinction = max(1e-4, dot(scattering, vec3(0.33333))); scattering *= shadows * M_PI; + /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ + scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0f; } void eval_volume_step(inout vec3 Lscat, float extinction, float step_len, out float Tr) diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index e6563b3113b..ba1d3d9ff5c 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -36,6 +36,8 @@ static struct { struct GPUShader *volume_sh; struct GPUShader *volume_slice_sh; + struct GPUTexture *dummy_tex; + struct GPUTexture *dummy_coba_tex; } e_data = {NULL}; extern char datatoc_workbench_volume_vert_glsl[]; @@ -50,6 +52,10 @@ void workbench_volume_engine_init(void) e_data.volume_slice_sh = DRW_shader_create( datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, "#define VOLUME_SLICE"); + + float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + e_data.dummy_tex = GPU_texture_create_3D(1, 1, 1, GPU_RGBA8, pixel, NULL); + e_data.dummy_coba_tex = GPU_texture_create_1D(1, GPU_RGBA8, pixel, NULL); } } @@ -57,6 +63,8 @@ void workbench_volume_engine_free(void) { DRW_SHADER_FREE_SAFE(e_data.volume_sh); DRW_SHADER_FREE_SAFE(e_data.volume_slice_sh); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_tex); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_coba_tex); } void workbench_volume_cache_init(WORKBENCH_Data *vedata) @@ -102,6 +110,8 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_slice_sh, vedata->psl->volume_pass); DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); + DRW_shgroup_uniform_texture(grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); + DRW_shgroup_uniform_texture(grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); @@ -109,7 +119,6 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); - /* TODO Flame rendering */ /* TODO COBA Rendering */ DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); @@ -122,6 +131,8 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); + DRW_shgroup_uniform_texture(grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); + DRW_shgroup_uniform_texture(grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slices); /* TODO FIXME : This step size is in object space but the ray itself @@ -131,7 +142,6 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); - /* TODO Flame rendering */ /* TODO COBA Rendering */ DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 594a2d6d740..b7b7d8f2a35 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -63,6 +63,7 @@ #include "IMB_imbuf_types.h" #include "BKE_bmfont.h" +#include "BKE_colorband.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_main.h" @@ -883,6 +884,106 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i BKE_image_release_ibuf(ima, ibuf, NULL); } +/* *************************** Transfer functions *************************** */ + +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 = 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 ColorBand *coba, float *data) +{ + for (int i = 0; i < TFUNC_WIDTH; i++) { + BKE_colorband_evaluate(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, GPU_RGBA8, 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], GPU_R8, field, NULL); +} + void GPU_free_smoke(SmokeModifierData *smd) { if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { @@ -897,6 +998,10 @@ void GPU_free_smoke(SmokeModifierData *smd) if (smd->domain->tex_flame) GPU_texture_free(smd->domain->tex_flame); smd->domain->tex_flame = NULL; + + if (smd->domain->tex_flame_coba) + GPU_texture_free(smd->domain->tex_flame_coba); + smd->domain->tex_flame_coba = NULL; } } @@ -966,12 +1071,16 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) sds->tex_flame = ( smoke_turbulence_has_fuel(sds->wt) ? GPU_texture_create_nD( - sds->res[0], sds->res[1], sds->res[2], 3, + sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 3, smoke_turbulence_get_flame(sds->wt), GPU_R8, GPU_DATA_FLOAT, 0, true, NULL) : NULL); } + if (sds->tex_flame) { + sds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL); + } + sds->tex_shadow = GPU_texture_create_nD( sds->res[0], sds->res[1], sds->res[2], 3, sds->shadow, @@ -982,6 +1091,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) (void)highres; smd->domain->tex = NULL; smd->domain->tex_flame = NULL; + smd->domain->tex_flame_coba = NULL; smd->domain->tex_shadow = NULL; #endif // WITH_SMOKE } diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index cc2f1a8c358..a09f766fc02 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -137,6 +137,7 @@ typedef struct SmokeDomainSettings { struct GPUTexture *tex_wt; struct GPUTexture *tex_shadow; struct GPUTexture *tex_flame; + struct GPUTexture *tex_flame_coba; struct GPUTexture *tex_velocity_x; struct GPUTexture *tex_velocity_y; struct GPUTexture *tex_velocity_z; |