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
diff options
context:
space:
mode:
-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;