Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-10-08 18:20:02 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-10-08 18:20:09 +0300
commite5c7c21630f9d67425bb3916cbc51deef185d2be (patch)
tree941be7912e9f31670e29c448e04d17178ed8cb51 /source
parent8c4a7593f2189a57d348f4c3caf9fc1e3d552059 (diff)
Workbench: Smoke: Port back Flame display
The appearance is a bit different than 2.79 where the flame was just added on top of the smoke without correct blending. Now it's much more realistic and using volumetric integration. You can see the smoke actually masking the flame. The other difference is that the flame color was not using proper color managed blending. Now with the use of filmic it shows bright yellow. This could be adjusted and displayed as a user parameter in the future.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl9
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c14
-rw-r--r--source/blender/gpu/intern/gpu_draw.c112
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h1
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;