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:
Diffstat (limited to 'source/blender/draw/engines/workbench')
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl83
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h12
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c21
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c148
5 files changed, 222 insertions, 48 deletions
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 aa938d80fa3..eaa553a10de 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -10,6 +10,7 @@ uniform sampler2D depthBuffer;
uniform sampler3D densityTexture;
uniform sampler3D shadowTexture;
uniform sampler3D flameTexture;
+uniform usampler3D flagTexture;
uniform sampler1D flameColorTexture;
uniform sampler1D transferTexture;
uniform mat4 volumeObjectToTexture;
@@ -18,11 +19,16 @@ uniform int samplesLen = 256;
uniform float noiseOfs = 0.0;
uniform float stepLength; /* Step length in local space. */
uniform float densityScale; /* Simple Opacity multiplicator. */
+uniform float gridScale; /* Multiplicator for grid scaling. */
uniform vec3 activeColor;
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+uniform bool showPhi = false;
+uniform bool showFlags = false;
+uniform bool showPressure = false;
+
#ifdef VOLUME_SLICE
in vec3 localPos;
#endif
@@ -91,18 +97,89 @@ vec4 sample_tricubic(sampler3D ima, vec3 co)
return color;
}
+/* Nearest-neighbor interpolation */
+vec4 sample_closest(sampler3D ima, vec3 co)
+{
+ /* Unnormalize coordinates */
+ ivec3 cell_co = ivec3(co * vec3(textureSize(ima, 0).xyz));
+
+ return texelFetch(ima, cell_co, 0);
+}
+
+vec4 flag_to_color(uint flag)
+{
+ /* Color mapping for flags */
+ vec4 color = vec4(0.0, 0.0, 0.0, 0.06);
+ /* Cell types: 1 is Fluid, 2 is Obstacle, 4 is Empty, 8 is Inflow, 16 is Outflow */
+ if (bool(flag & uint(1))) {
+ color.rgb += vec3(0.0, 0.0, 0.75); /* blue */
+ }
+ if (bool(flag & uint(2))) {
+ color.rgb += vec3(0.2, 0.2, 0.2); /* dark gray */
+ }
+ if (bool(flag & uint(4))) {
+ color.rgb += vec3(0.25, 0.0, 0.2); /* dark purple */
+ }
+ if (bool(flag & uint(8))) {
+ color.rgb += vec3(0.0, 0.5, 0.0); /* dark green */
+ }
+ if (bool(flag & uint(16))) {
+ color.rgb += vec3(0.9, 0.3, 0.0); /* orange */
+ }
+ if (color.rgb == vec3(0.0)) {
+ color.rgb += vec3(0.5, 0.0, 0.0); /* medium red */
+ }
+ return color;
+}
+
#ifdef USE_TRICUBIC
# define sample_volume_texture sample_tricubic
-#else
+#elif defined(USE_TRILINEAR)
# define sample_volume_texture sample_trilinear
+#elif defined(USE_CLOSEST)
+# define sample_volume_texture sample_closest
#endif
void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
{
vec3 co = ls_pos * 0.5 + 0.5;
#ifdef USE_COBA
- float val = sample_volume_texture(densityTexture, co).r;
- vec4 tval = texture(transferTexture, val) * densityScale;
+ vec4 tval;
+ if (showPhi) {
+ /* Color mapping for level-set representation */
+ float val = sample_volume_texture(densityTexture, co).r * gridScale;
+
+ val = max(min(val * 0.2, 1.0), -1.0);
+
+ if (val >= 0.0) {
+ tval = vec4(val, 0.0, 0.5, 0.06);
+ }
+ else {
+ tval = vec4(0.5, 1.0 + val, 0.0, 0.06);
+ }
+ }
+ else if (showFlags) {
+ /* Color mapping for flags */
+ uint flag = texture(flagTexture, co).r;
+ tval = flag_to_color(flag);
+ }
+ else if (showPressure) {
+ /* Color mapping for pressure */
+ float val = sample_volume_texture(densityTexture, co).r * gridScale;
+
+ if (val > 0) {
+ tval = vec4(val, val, val, 0.06);
+ }
+ else {
+ tval = vec4(-val, 0.0, 0.0, 0.06);
+ }
+ }
+ else {
+ float val = sample_volume_texture(densityTexture, co).r * gridScale;
+ tval = texture(transferTexture, val);
+ }
+ tval *= densityScale;
+ tval.rgb = pow(tval.rgb, vec3(2.2));
scattering = tval.rgb * 1500.0;
extinction = max(1e-4, tval.a * 50.0);
#else
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 80a8f310191..ed9cb17ae28 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -367,9 +367,11 @@ void workbench_cache_populate(void *ved, Object *ob)
ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (md && BKE_modifier_is_enabled(wpd->scene, md, eModifierMode_Realtime)) {
FluidModifierData *fmd = (FluidModifierData *)md;
- if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
+ if (fmd->domain) {
workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR);
- return; /* Do not draw solid in this case. */
+ if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
+ return; /* Do not draw solid in this case. */
+ }
}
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index d377f09ac73..81793367768 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -82,6 +82,13 @@ typedef enum eWORKBENCH_DataType {
WORKBENCH_DATATYPE_MAX,
} eWORKBENCH_DataType;
+/* Types of volume display interpolation. */
+typedef enum eWORKBENCH_VolumeInterpType {
+ WORKBENCH_VOLUME_INTERP_LINEAR = 0,
+ WORKBENCH_VOLUME_INTERP_CUBIC,
+ WORKBENCH_VOLUME_INTERP_CLOSEST,
+} eWORKBENCH_VolumeInterpType;
+
typedef struct WORKBENCH_FramebufferList {
struct GPUFrameBuffer *opaque_fb;
struct GPUFrameBuffer *opaque_infront_fb;
@@ -428,7 +435,10 @@ GPUShader *workbench_shader_outline_get(void);
GPUShader *workbench_shader_antialiasing_accumulation_get(void);
GPUShader *workbench_shader_antialiasing_get(int stage);
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke);
+GPUShader *workbench_shader_volume_get(bool slice,
+ bool coba,
+ eWORKBENCH_VolumeInterpType interp_type,
+ bool smoke);
void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **downsample_sh,
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index af3b5d31b2b..b3b9e11ae58 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -111,7 +111,7 @@ static struct {
struct GPUShader *aa_accum_sh;
struct GPUShader *smaa_sh[3];
- struct GPUShader *volume_sh[2][2][2][2];
+ struct GPUShader *volume_sh[2][2][3][2];
struct DRWShaderLibrary *lib;
} e_data = {{{{NULL}}}};
@@ -463,9 +463,12 @@ GPUShader *workbench_shader_antialiasing_get(int stage)
return e_data.smaa_sh[stage];
}
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke)
+GPUShader *workbench_shader_volume_get(bool slice,
+ bool coba,
+ eWORKBENCH_VolumeInterpType interp_type,
+ bool smoke)
{
- GPUShader **shader = &e_data.volume_sh[slice][coba][cubic][smoke];
+ GPUShader **shader = &e_data.volume_sh[slice][coba][interp_type][smoke];
if (*shader == NULL) {
DynStr *ds = BLI_dynstr_new();
@@ -476,8 +479,16 @@ GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool s
if (coba) {
BLI_dynstr_append(ds, "#define USE_COBA\n");
}
- if (cubic) {
- BLI_dynstr_append(ds, "#define USE_TRICUBIC\n");
+ switch (interp_type) {
+ case WORKBENCH_VOLUME_INTERP_LINEAR:
+ BLI_dynstr_append(ds, "#define USE_TRILINEAR\n");
+ break;
+ case WORKBENCH_VOLUME_INTERP_CUBIC:
+ BLI_dynstr_append(ds, "#define USE_TRICUBIC\n");
+ break;
+ case WORKBENCH_VOLUME_INTERP_CLOSEST:
+ BLI_dynstr_append(ds, "#define USE_CLOSEST\n");
+ break;
}
if (smoke) {
BLI_dynstr_append(ds, "#define VOLUME_SMOKE\n");
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index 7aa089d440f..c76f4a4c470 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -45,8 +45,10 @@ void workbench_volume_engine_init(WORKBENCH_Data *vedata)
if (txl->dummy_volume_tx == NULL) {
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- txl->dummy_volume_tx = GPU_texture_create_3d("dummy_volume", 1, 1, 1, 1, GPU_RGBA8, zero);
- txl->dummy_shadow_tx = GPU_texture_create_3d("dummy_shadow", 1, 1, 1, 1, GPU_RGBA8, one);
+ txl->dummy_volume_tx = GPU_texture_create_3d(
+ "dummy_volume", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, zero);
+ txl->dummy_shadow_tx = GPU_texture_create_3d(
+ "dummy_shadow", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, one);
txl->dummy_coba_tx = GPU_texture_create_1d("dummy_coba", 1, 1, GPU_RGBA8, zero);
}
}
@@ -70,8 +72,7 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRWShadingGroup *grp = NULL;
- /* Don't try to show liquid domains here */
- if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) {
+ if (!fds->fluid) {
return;
}
@@ -79,19 +80,41 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
if (fds->use_coba) {
DRW_smoke_ensure_coba_field(fmd);
}
- else {
+ else if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE);
}
+ else {
+ return;
+ }
if ((!fds->use_coba && (fds->tex_density == NULL && fds->tex_color == NULL)) ||
(fds->use_coba && fds->tex_field == NULL)) {
return;
}
- const bool use_slice = (fds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
- fds->axis_slice_method == AXIS_SLICE_SINGLE);
- const bool cubic_interp = (fds->interp_method == VOLUME_INTERP_CUBIC);
- GPUShader *sh = workbench_shader_volume_get(use_slice, fds->use_coba, cubic_interp, true);
+ const bool use_slice = (fds->axis_slice_method == AXIS_SLICE_SINGLE);
+ const bool show_phi = ELEM(fds->coba_field,
+ FLUID_DOMAIN_FIELD_PHI,
+ FLUID_DOMAIN_FIELD_PHI_IN,
+ FLUID_DOMAIN_FIELD_PHI_OUT,
+ FLUID_DOMAIN_FIELD_PHI_OBSTACLE);
+ const bool show_flags = (fds->coba_field == FLUID_DOMAIN_FIELD_FLAGS);
+ const bool show_pressure = (fds->coba_field == FLUID_DOMAIN_FIELD_PRESSURE);
+ eWORKBENCH_VolumeInterpType interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
+
+ switch ((FLUID_DisplayInterpolationMethod)fds->interp_method) {
+ case FLUID_DISPLAY_INTERP_LINEAR:
+ interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
+ break;
+ case FLUID_DISPLAY_INTERP_CUBIC:
+ interp_type = WORKBENCH_VOLUME_INTERP_CUBIC;
+ break;
+ case FLUID_DISPLAY_INTERP_CLOSEST:
+ interp_type = WORKBENCH_VOLUME_INTERP_CLOSEST;
+ break;
+ }
+
+ GPUShader *sh = workbench_shader_volume_get(use_slice, fds->use_coba, interp_type, true);
if (use_slice) {
float invviewmat[4][4];
@@ -106,6 +129,7 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
float step_length = max_ff(1e-16f, dim[axis] * 0.05f);
grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_float_copy(grp, "slicePosition", fds->slice_depth);
DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
@@ -132,8 +156,19 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
}
if (fds->use_coba) {
- DRW_shgroup_uniform_texture(grp, "densityTexture", fds->tex_field);
- DRW_shgroup_uniform_texture(grp, "transferTexture", fds->tex_coba);
+ if (show_flags) {
+ DRW_shgroup_uniform_texture(grp, "flagTexture", fds->tex_field);
+ }
+ else {
+ DRW_shgroup_uniform_texture(grp, "densityTexture", fds->tex_field);
+ }
+ if (!show_phi && !show_flags && !show_pressure) {
+ DRW_shgroup_uniform_texture(grp, "transferTexture", fds->tex_coba);
+ }
+ DRW_shgroup_uniform_float_copy(grp, "gridScale", fds->grid_scale);
+ DRW_shgroup_uniform_bool_copy(grp, "showPhi", show_phi);
+ DRW_shgroup_uniform_bool_copy(grp, "showFlags", show_flags);
+ DRW_shgroup_uniform_bool_copy(grp, "showPressure", show_pressure);
}
else {
static float white[3] = {1.0f, 1.0f, 1.0f};
@@ -192,11 +227,26 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
WORKBENCH_TextureList *txl = vedata->txl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DRWShadingGroup *grp = NULL;
wpd->volumes_do = true;
+ const bool use_slice = (volume->display.axis_slice_method == AXIS_SLICE_SINGLE);
+ eWORKBENCH_VolumeInterpType interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
+
+ switch ((VolumeDisplayInterpMethod)volume->display.interpolation_method) {
+ case VOLUME_DISPLAY_INTERP_LINEAR:
+ interp_type = WORKBENCH_VOLUME_INTERP_LINEAR;
+ break;
+ case VOLUME_DISPLAY_INTERP_CUBIC:
+ interp_type = WORKBENCH_VOLUME_INTERP_CUBIC;
+ break;
+ case VOLUME_DISPLAY_INTERP_CLOSEST:
+ interp_type = WORKBENCH_VOLUME_INTERP_CLOSEST;
+ break;
+ }
/* Create shader. */
- GPUShader *sh = workbench_shader_volume_get(false, false, false, false);
+ GPUShader *sh = workbench_shader_volume_get(use_slice, false, interp_type, false);
/* Compute color. */
float color[3];
@@ -206,36 +256,60 @@ static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
float texture_to_world[4][4];
mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object);
- /* Compute world space dimensions for step size. */
- float world_size[3];
- mat4_to_size(world_size, texture_to_world);
- abs_v3(world_size);
-
- /* Compute step parameters. */
- double noise_ofs;
- BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
- float step_length, max_slice;
- int resolution[3];
- GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
- float slice_ct[3] = {resolution[0], resolution[1], resolution[2]};
- mul_v3_fl(slice_ct, max_ff(0.001f, 5.0f));
- max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]);
- invert_v3(slice_ct);
- mul_v3_v3(slice_ct, world_size);
- step_length = len_v3(slice_ct);
+ if (use_slice) {
+ float invviewmat[4][4];
+ DRW_view_viewmat_get(NULL, invviewmat, true);
+
+ const int axis = (volume->display.slice_axis == SLICE_AXIS_AUTO) ?
+ axis_dominant_v3_single(invviewmat[2]) :
+ volume->display.slice_axis - 1;
+
+ float dim[3];
+ BKE_object_dimensions_get(ob, dim);
+ /* 0.05f to achieve somewhat the same opacity as the full view. */
+ float step_length = max_ff(1e-16f, dim[axis] * 0.05f);
+
+ const float slice_position = volume->display.slice_depth;
+
+ grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", slice_position);
+ DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
+ DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
+ DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT);
+ }
+ else {
+ /* Compute world space dimensions for step size. */
+ float world_size[3];
+ mat4_to_size(world_size, texture_to_world);
+ abs_v3(world_size);
+
+ /* Compute step parameters. */
+ double noise_ofs;
+ BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
+ float step_length, max_slice;
+ int resolution[3];
+ GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
+ float slice_ct[3] = {resolution[0], resolution[1], resolution[2]};
+ mul_v3_fl(slice_ct, max_ff(0.001f, 5.0f));
+ max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]);
+ invert_v3(slice_ct);
+ mul_v3_v3(slice_ct, world_size);
+ step_length = len_v3(slice_ct);
+
+ /* Set uniforms. */
+ grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
+ DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
+ DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
+ }
/* Compute density scale. */
const float density_scale = volume->display.density *
BKE_volume_density_scale(volume, ob->obmat);
- /* Set uniforms. */
- DRWShadingGroup *grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
- DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
- DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
- DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
- DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
-
DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture);
/* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
DRW_shgroup_uniform_texture(grp, "shadowTexture", txl->dummy_shadow_tx);