[Bf-blender-cvs] [e5c7c21630f] blender2.8: Workbench: Smoke: Port back Flame display

Clément Foucault noreply at git.blender.org
Mon Oct 8 17:20:24 CEST 2018


Commit: e5c7c21630f9d67425bb3916cbc51deef185d2be
Author: Clément Foucault
Date:   Mon Oct 8 17:20:02 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBe5c7c21630f9d67425bb3916cbc51deef185d2be

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.

===================================================================

M	source/blender/blenloader/intern/readfile.c
M	source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
M	source/blender/draw/engines/workbench/workbench_volume.c
M	source/blender/gpu/intern/gpu_draw.c
M	source/blender/makesdna/DNA_smoke_types.h

===================================================================

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,
+			            

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list