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:
authorSriharsha Kotcharlakot <k.venkatsriharsha@gmail.com>2020-09-15 18:51:14 +0300
committerSriharsha Kotcharlakot <k.venkatsriharsha@gmail.com>2020-09-15 20:43:01 +0300
commitf137022f9919f4dd315ec6b325a08e1bf5aec6fb (patch)
tree4b15aa230eb100e77b41dfffb8ef5e7501c55db5 /source/blender/draw
parentbedbd8655ed1d331aeaf756874c46dbed93168a1 (diff)
Liquid Simulation Display Options (GSoC 2020)
All the changes made in the branch `soc-2020-fluid-tools` are included in this patch. **Major changes:** === Viewport Display === - //Raw voxel display// or //closest (nearest-neighbor)// interpolation for displaying the underlying voxel data of the simulation grids more clearly. - An option to display //gridlines// when the slicing method is //single//. ==== Grid Display ==== - Visualization for flags, pressure and level-set representation grids with a fixed color coding based on Manta GUI. ==== Vector Display ==== - //**M**arker **A**nd **C**ell// grid visualization options for vector grids like velocity or external forces. - Made vector display options available for external forces. ==== Coloring options for //gridlines// ==== - Range highlighting and cell filtering options for displaying the simulation grid data more precisely. - Color gridlines with flags. - Also, made slicing and interpolation options available for Volume Object. Reviewed By: JacquesLucke, sebbas Differential Revision: https://developer.blender.org/D8705
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c88
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h3
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c65
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl121
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl118
-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
-rw-r--r--source/blender/draw/intern/draw_cache_impl_volume.c2
-rw-r--r--source/blender/draw/intern/draw_common.h2
-rw-r--r--source/blender/draw/intern/draw_fluid.c159
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c3
-rw-r--r--source/blender/draw/tests/shaders_test.cc63
16 files changed, 783 insertions, 112 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index af264365c25..089b656d76c 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -409,6 +409,7 @@ data_to_c_simple(engines/overlay/shaders/particle_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/sculpt_mask_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC)
+data_to_c_simple(engines/overlay/shaders/volume_gridlines_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC)
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index ce678c7d03f..09061450a1a 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1383,6 +1383,17 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
const bool draw_velocity = (fds->draw_velocity && fds->fluid &&
CFRA >= fds->point_cache[0]->startframe);
+ /* Show gridlines only for slices with no interpolation. */
+ const bool show_gridlines = (fds->show_gridlines && fds->fluid &&
+ fds->axis_slice_method == AXIS_SLICE_SINGLE &&
+ (fds->interp_method == FLUID_DISPLAY_INTERP_CLOSEST ||
+ fds->coba_field == FLUID_DOMAIN_FIELD_FLAGS));
+
+ const bool color_with_flags = (fds->gridlines_color_field == FLUID_GRIDLINE_COLOR_TYPE_FLAGS);
+
+ const bool color_range = (fds->gridlines_color_field == FLUID_GRIDLINE_COLOR_TYPE_RANGE &&
+ fds->use_coba && fds->coba_field != FLUID_DOMAIN_FIELD_FLAGS);
+
/* Small cube showing voxel size. */
{
float min[3];
@@ -1402,26 +1413,40 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
DRW_buffer_add_entry(cb->empty_cube, color, voxel_cubemat);
}
+ int slice_axis = -1;
+
+ if (fds->axis_slice_method == AXIS_SLICE_SINGLE) {
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
+
+ const int axis = (fds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) :
+ fds->slice_axis - 1;
+ slice_axis = axis;
+ }
+
if (draw_velocity) {
const bool use_needle = (fds->vector_draw_type == VECTOR_DRAW_NEEDLE);
- int line_count = (use_needle) ? 6 : 1;
- int slice_axis = -1;
+ const bool use_mac = (fds->vector_draw_type == VECTOR_DRAW_MAC);
+ const bool draw_mac_x = (fds->vector_draw_mac_components & VECTOR_DRAW_MAC_X);
+ const bool draw_mac_y = (fds->vector_draw_mac_components & VECTOR_DRAW_MAC_Y);
+ const bool draw_mac_z = (fds->vector_draw_mac_components & VECTOR_DRAW_MAC_Z);
+ const bool cell_centered = (fds->vector_field == FLUID_DOMAIN_VECTOR_FIELD_FORCE);
+ int line_count = 1;
+ if (use_needle) {
+ line_count = 6;
+ }
+ else if (use_mac) {
+ line_count = 3;
+ }
line_count *= fds->res[0] * fds->res[1] * fds->res[2];
- if (fds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
- fds->axis_slice_method == AXIS_SLICE_SINGLE) {
- float viewinv[4][4];
- DRW_view_viewmat_get(NULL, viewinv, true);
-
- const int axis = (fds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) :
- fds->slice_axis - 1;
- slice_axis = axis;
- line_count /= fds->res[axis];
+ if (fds->axis_slice_method == AXIS_SLICE_SINGLE) {
+ line_count /= fds->res[slice_axis];
}
DRW_smoke_ensure_velocity(fmd);
- GPUShader *sh = OVERLAY_shader_volume_velocity(use_needle);
+ GPUShader *sh = OVERLAY_shader_volume_velocity(use_needle, use_mac);
DRWShadingGroup *grp = DRW_shgroup_create(sh, data->psl->extra_ps[0]);
DRW_shgroup_uniform_texture(grp, "velocityX", fds->tex_velocity_x);
DRW_shgroup_uniform_texture(grp, "velocityY", fds->tex_velocity_y);
@@ -1432,8 +1457,47 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
DRW_shgroup_uniform_vec3_copy(grp, "domainOriginOffset", fds->p0);
DRW_shgroup_uniform_ivec3_copy(grp, "adaptiveCellOffset", fds->res_min);
DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis);
+ DRW_shgroup_uniform_bool_copy(grp, "scaleWithMagnitude", fds->vector_scale_with_magnitude);
+ DRW_shgroup_uniform_bool_copy(grp, "isCellCentered", cell_centered);
+
+ if (use_mac) {
+ DRW_shgroup_uniform_bool_copy(grp, "drawMACX", draw_mac_x);
+ DRW_shgroup_uniform_bool_copy(grp, "drawMACY", draw_mac_y);
+ DRW_shgroup_uniform_bool_copy(grp, "drawMACZ", draw_mac_z);
+ }
+
+ DRW_shgroup_call_procedural_lines(grp, ob, line_count);
+ }
+
+ if (show_gridlines) {
+ GPUShader *sh = OVERLAY_shader_volume_gridlines(color_with_flags, color_range);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, data->psl->extra_ps[0]);
+ DRW_shgroup_uniform_ivec3_copy(grp, "volumeSize", fds->res);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", fds->slice_depth);
+ DRW_shgroup_uniform_vec3_copy(grp, "cellSize", fds->cell_size);
+ DRW_shgroup_uniform_vec3_copy(grp, "domainOriginOffset", fds->p0);
+ DRW_shgroup_uniform_ivec3_copy(grp, "adaptiveCellOffset", fds->res_min);
+ DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis);
+
+ if (color_with_flags || color_range) {
+ DRW_fluid_ensure_flags(fmd);
+ DRW_shgroup_uniform_texture(grp, "flagTexture", fds->tex_flags);
+ }
+
+ if (color_range) {
+ DRW_fluid_ensure_range_field(fmd);
+ DRW_shgroup_uniform_texture(grp, "fieldTexture", fds->tex_range_field);
+ DRW_shgroup_uniform_float_copy(grp, "lowerBound", fds->gridlines_lower_bound);
+ DRW_shgroup_uniform_float_copy(grp, "upperBound", fds->gridlines_upper_bound);
+ DRW_shgroup_uniform_vec4_copy(grp, "rangeColor", fds->gridlines_range_color);
+ DRW_shgroup_uniform_int_copy(grp, "cellFilter", fds->gridlines_cell_filter);
+ }
+
+ const int line_count = 4 * fds->res[0] * fds->res[1] * fds->res[2] / fds->res[slice_axis];
DRW_shgroup_call_procedural_lines(grp, ob, line_count);
+ }
+ if (draw_velocity || show_gridlines) {
BLI_addtail(&data->stl->pd->smoke_domains, BLI_genericNodeN(fmd));
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index c8b29c6bbbb..c684f420b19 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -685,7 +685,8 @@ GPUShader *OVERLAY_shader_paint_wire(void);
GPUShader *OVERLAY_shader_particle_dot(void);
GPUShader *OVERLAY_shader_particle_shape(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
-GPUShader *OVERLAY_shader_volume_velocity(bool use_needle);
+GPUShader *OVERLAY_shader_volume_velocity(bool use_needle, bool use_mac);
+GPUShader *OVERLAY_shader_volume_gridlines(bool color_with_flags, bool color_range);
GPUShader *OVERLAY_shader_wireframe(bool custom_bias);
GPUShader *OVERLAY_shader_wireframe_select(void);
GPUShader *OVERLAY_shader_xray_fade(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 4530d6e8adf..5c1b7c786f4 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -115,6 +115,7 @@ extern char datatoc_particle_frag_glsl[];
extern char datatoc_sculpt_mask_vert_glsl[];
extern char datatoc_sculpt_mask_frag_glsl[];
extern char datatoc_volume_velocity_vert_glsl[];
+extern char datatoc_volume_gridlines_vert_glsl[];
extern char datatoc_wireframe_vert_glsl[];
extern char datatoc_wireframe_frag_glsl[];
extern char datatoc_xray_fade_frag_glsl[];
@@ -214,7 +215,11 @@ typedef struct OVERLAY_Shaders {
GPUShader *sculpt_mask;
GPUShader *uniform_color;
GPUShader *volume_velocity_needle_sh;
+ GPUShader *volume_velocity_mac_sh;
GPUShader *volume_velocity_sh;
+ GPUShader *volume_gridlines_sh;
+ GPUShader *volume_gridlines_flags_sh;
+ GPUShader *volume_gridlines_range_sh;
GPUShader *wireframe_select;
GPUShader *wireframe[2];
GPUShader *xray_fade;
@@ -1414,7 +1419,7 @@ struct GPUShader *OVERLAY_shader_uniform_color(void)
return sh_data->uniform_color;
}
-struct GPUShader *OVERLAY_shader_volume_velocity(bool use_needle)
+struct GPUShader *OVERLAY_shader_volume_velocity(bool use_needle, bool use_mac)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
if (use_needle && !sh_data->volume_velocity_needle_sh) {
@@ -1426,6 +1431,15 @@ struct GPUShader *OVERLAY_shader_volume_velocity(bool use_needle)
"#define blender_srgb_to_framebuffer_space(a) a\n"
"#define USE_NEEDLE\n");
}
+ else if (use_mac && !sh_data->volume_velocity_mac_sh) {
+ sh_data->volume_velocity_mac_sh = DRW_shader_create_with_lib(
+ datatoc_volume_velocity_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_3D_smooth_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define blender_srgb_to_framebuffer_space(a) a\n"
+ "#define USE_MAC\n");
+ }
else if (!sh_data->volume_velocity_sh) {
sh_data->volume_velocity_sh = DRW_shader_create_with_lib(
datatoc_volume_velocity_vert_glsl,
@@ -1434,7 +1448,54 @@ struct GPUShader *OVERLAY_shader_volume_velocity(bool use_needle)
datatoc_common_view_lib_glsl,
"#define blender_srgb_to_framebuffer_space(a) a\n");
}
- return (use_needle) ? sh_data->volume_velocity_needle_sh : sh_data->volume_velocity_sh;
+ if (use_needle) {
+ return sh_data->volume_velocity_needle_sh;
+ }
+ if (use_mac) {
+ return sh_data->volume_velocity_mac_sh;
+ }
+
+ return sh_data->volume_velocity_sh;
+}
+
+struct GPUShader *OVERLAY_shader_volume_gridlines(bool color_with_flags, bool color_range)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->volume_gridlines_flags_sh && color_with_flags) {
+ sh_data->volume_gridlines_flags_sh = DRW_shader_create_with_lib(
+ datatoc_volume_gridlines_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define blender_srgb_to_framebuffer_space(a) a\n"
+ "#define SHOW_FLAGS\n");
+ }
+ else if (!sh_data->volume_gridlines_range_sh && color_range) {
+ sh_data->volume_gridlines_range_sh = DRW_shader_create_with_lib(
+ datatoc_volume_gridlines_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define blender_srgb_to_framebuffer_space(a) a\n"
+ "#define SHOW_RANGE\n");
+ }
+ else if (!sh_data->volume_gridlines_sh) {
+ sh_data->volume_gridlines_sh = DRW_shader_create_with_lib(
+ datatoc_volume_gridlines_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+
+ if (color_with_flags) {
+ return sh_data->volume_gridlines_flags_sh;
+ }
+ if (color_range) {
+ return sh_data->volume_gridlines_range_sh;
+ }
+
+ return sh_data->volume_gridlines_sh;
}
GPUShader *OVERLAY_shader_wireframe_select(void)
diff --git a/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl
new file mode 100644
index 00000000000..f714646fe40
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl
@@ -0,0 +1,121 @@
+uniform float slicePosition;
+uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+
+/* FluidDomainSettings.res */
+uniform ivec3 volumeSize;
+/* FluidDomainSettings.cell_size */
+uniform vec3 cellSize;
+/* FluidDomainSettings.p0 */
+uniform vec3 domainOriginOffset;
+/* FluidDomainSettings.res_min */
+uniform ivec3 adaptiveCellOffset;
+
+#if defined(SHOW_FLAGS) || defined(SHOW_RANGE)
+uniform usampler3D flagTexture;
+#endif
+
+#ifdef SHOW_RANGE
+uniform sampler3D fieldTexture;
+uniform float lowerBound = 0.0;
+uniform float upperBound = 0.0;
+uniform vec4 rangeColor;
+uniform int cellFilter;
+#endif
+
+flat out vec4 finalColor;
+
+/* Corners for cell outlines. 0.45 is arbitrary. Any value below 0.5 can be used to avoid
+ * overlapping of the outlines. */
+const vec3 corners[4] = vec3[4](vec3(-0.45, 0.45, 0.0),
+ vec3(0.45, 0.45, 0.0),
+ vec3(0.45, -0.45, 0.0),
+ vec3(-0.45, -0.45, 0.0));
+
+const int indices[8] = int[8](0, 1, 1, 2, 2, 3, 3, 0);
+
+vec4 flag_to_color(uint flag)
+{
+ /* Color mapping for flags */
+ vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
+ /* 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.4, 0.4, 0.4); /* 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;
+}
+
+void main()
+{
+ int cell = gl_VertexID / 8;
+ mat3 rot_mat = mat3(0.0);
+
+ vec3 cell_offset = vec3(0.5);
+ ivec3 cell_div = volumeSize;
+ if (sliceAxis == 0) {
+ cell_offset.x = slicePosition * float(volumeSize.x);
+ cell_div.x = 1;
+ rot_mat[2].x = 1.0;
+ rot_mat[0].y = 1.0;
+ rot_mat[1].z = 1.0;
+ }
+ else if (sliceAxis == 1) {
+ cell_offset.y = slicePosition * float(volumeSize.y);
+ cell_div.y = 1;
+ rot_mat[1].x = 1.0;
+ rot_mat[2].y = 1.0;
+ rot_mat[0].z = 1.0;
+ }
+ else if (sliceAxis == 2) {
+ cell_offset.z = slicePosition * float(volumeSize.z);
+ cell_div.z = 1;
+ rot_mat[0].x = 1.0;
+ rot_mat[1].y = 1.0;
+ rot_mat[2].z = 1.0;
+ }
+
+ ivec3 cell_co;
+ cell_co.x = cell % cell_div.x;
+ cell_co.y = (cell / cell_div.x) % cell_div.y;
+ cell_co.z = cell / (cell_div.x * cell_div.y);
+
+ finalColor = vec4(0.0, 0.0, 0.0, 1.0);
+
+#if defined(SHOW_FLAGS) || defined(SHOW_RANGE)
+ uint flag = texelFetch(flagTexture, cell_co + ivec3(cell_offset), 0).r;
+#endif
+
+#ifdef SHOW_FLAGS
+ finalColor = flag_to_color(flag);
+#endif
+
+#ifdef SHOW_RANGE
+ float value = texelFetch(fieldTexture, cell_co + ivec3(cell_offset), 0).r;
+ if (value >= lowerBound && value <= upperBound) {
+ if (cellFilter == 0 || bool(uint(cellFilter) & flag)) {
+ finalColor = rangeColor;
+ }
+ }
+#endif
+
+ vec3 pos = domainOriginOffset + cellSize * (vec3(cell_co + adaptiveCellOffset) + cell_offset);
+ vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 8]];
+ pos += rotated_pos * cellSize;
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
index 752694301f7..0b827601f8e 100644
--- a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
@@ -5,6 +5,8 @@ uniform sampler3D velocityZ;
uniform float displaySize = 1.0;
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+uniform bool scaleWithMagnitude = false;
+uniform bool isCellCentered = false;
/* FluidDomainSettings.cell_size */
uniform vec3 cellSize;
@@ -13,7 +15,15 @@ uniform vec3 domainOriginOffset;
/* FluidDomainSettings.res_min */
uniform ivec3 adaptiveCellOffset;
+#ifdef USE_MAC
+uniform bool drawMACX;
+uniform bool drawMACY;
+uniform bool drawMACZ;
+
+out vec4 finalColor;
+#else
flat out vec4 finalColor;
+#endif
const vec3 corners[4] = vec3[4](vec3(0.0, 0.2, -0.5),
vec3(-0.2 * 0.866, -0.2 * 0.5, -0.5),
@@ -64,10 +74,53 @@ mat3 rotation_from_vector(vec3 v)
return mat3(T, B, N);
}
+vec3 get_vector(ivec3 cell_co)
+{
+ vec3 vector;
+
+ vector.x = texelFetch(velocityX, cell_co, 0).r;
+ vector.y = texelFetch(velocityY, cell_co, 0).r;
+ vector.z = texelFetch(velocityZ, cell_co, 0).r;
+
+ return vector;
+}
+
+/* Interpolate MAC information for cell-centered vectors. */
+vec3 get_vector_centered(ivec3 cell_co)
+{
+ vec3 vector;
+
+ vector.x = 0.5 * (texelFetch(velocityX, cell_co, 0).r +
+ texelFetch(velocityX, ivec3(cell_co.x + 1, cell_co.yz), 0).r);
+ vector.y = 0.5 * (texelFetch(velocityY, cell_co, 0).r +
+ texelFetch(velocityY, ivec3(cell_co.x, cell_co.y + 1, cell_co.z), 0).r);
+ vector.z = 0.5 * (texelFetch(velocityZ, cell_co, 0).r +
+ texelFetch(velocityZ, ivec3(cell_co.xy, cell_co.z + 1), 0).r);
+
+ return vector;
+}
+
+/* Interpolate cell-centered information for MAC vectors. */
+vec3 get_vector_mac(ivec3 cell_co)
+{
+ vec3 vector;
+
+ vector.x = 0.5 * (texelFetch(velocityX, ivec3(cell_co.x - 1, cell_co.yz), 0).r +
+ texelFetch(velocityX, cell_co, 0).r);
+ vector.y = 0.5 * (texelFetch(velocityY, ivec3(cell_co.x, cell_co.y - 1, cell_co.z), 0).r +
+ texelFetch(velocityY, cell_co, 0).r);
+ vector.z = 0.5 * (texelFetch(velocityZ, ivec3(cell_co.xy, cell_co.z - 1), 0).r +
+ texelFetch(velocityZ, cell_co, 0).r);
+
+ return vector;
+}
+
void main()
{
#ifdef USE_NEEDLE
int cell = gl_VertexID / 12;
+#elif defined(USE_MAC)
+ int cell = gl_VertexID / 6;
#else
int cell = gl_VertexID / 2;
#endif
@@ -97,19 +150,64 @@ void main()
vec3 pos = domainOriginOffset + cellSize * (vec3(cell_co + adaptiveCellOffset) + 0.5);
- vec3 velocity;
- velocity.x = texelFetch(velocityX, cell_co, 0).r;
- velocity.y = texelFetch(velocityY, cell_co, 0).r;
- velocity.z = texelFetch(velocityZ, cell_co, 0).r;
+ vec3 vector;
+
+#ifdef USE_MAC
+ vec3 color;
+ vector = (isCellCentered) ? get_vector_mac(cell_co) : get_vector(cell_co);
+
+ switch (gl_VertexID % 6) {
+ case 0: /* Tail of X component. */
+ pos.x += (drawMACX) ? -0.5 * cellSize.x : 0.0;
+ color = vec3(1.0, 0.0, 0.0); /* red */
+ break;
+ case 1: /* Head of X component. */
+ pos.x += (drawMACX) ? (-0.5 + vector.x * displaySize) * cellSize.x : 0.0;
+ color = vec3(1.0, 1.0, 0.0); /* yellow */
+ break;
+ case 2: /* Tail of Y component. */
+ pos.y += (drawMACY) ? -0.5 * cellSize.y : 0.0;
+ color = vec3(0.0, 1.0, 0.0); /* green */
+ break;
+ case 3: /* Head of Y component. */
+ pos.y += (drawMACY) ? (-0.5 + vector.y * displaySize) * cellSize.y : 0.0;
+ color = vec3(1.0, 1.0, 0.0); /* yellow */
+ break;
+ case 4: /* Tail of Z component. */
+ pos.z += (drawMACZ) ? -0.5 * cellSize.z : 0.0;
+ color = vec3(0.0, 0.0, 1.0); /* blue */
+ break;
+ case 5: /* Head of Z component. */
+ pos.z += (drawMACZ) ? (-0.5 + vector.z * displaySize) * cellSize.z : 0.0;
+ color = vec3(1.0, 1.0, 0.0); /* yellow */
+ break;
+ }
- finalColor = vec4(weight_to_color(length(velocity)), 1.0);
+ finalColor = vec4(color, 1.0);
+#else
+ vector = (isCellCentered) ? get_vector(cell_co) : get_vector_centered(cell_co);
-#ifdef USE_NEEDLE
- mat3 rot_mat = rotation_from_vector(velocity);
+ finalColor = vec4(weight_to_color(length(vector)), 1.0);
+
+ float vector_length = 1.0;
+
+ if (scaleWithMagnitude) {
+ vector_length = length(vector);
+ }
+ else if (length(vector) == 0.0) {
+ vector_length = 0.0;
+ }
+
+ mat3 rot_mat = rotation_from_vector(vector);
+
+# ifdef USE_NEEDLE
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]];
- pos += rotated_pos * length(velocity) * displaySize * cellSize;
-#else
- pos += ((gl_VertexID % 2) == 1) ? velocity * displaySize * cellSize : vec3(0.0);
+ pos += rotated_pos * vector_length * displaySize * cellSize;
+# else
+ vec3 rotated_pos = rot_mat * vec3(0.0, 0.0, 1.0);
+ pos += ((gl_VertexID % 2) == 1) ? rotated_pos * vector_length * displaySize * cellSize :
+ vec3(0.0);
+# endif
#endif
vec3 world_pos = point_object_to_world(pos);
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);
diff --git a/source/blender/draw/intern/draw_cache_impl_volume.c b/source/blender/draw/intern/draw_cache_impl_volume.c
index 10b9623175c..e39c4976e38 100644
--- a/source/blender/draw/intern/draw_cache_impl_volume.c
+++ b/source/blender/draw/intern/draw_cache_impl_volume.c
@@ -260,7 +260,7 @@ static DRWVolumeGrid *volume_grid_cache_get(Volume *volume,
/* Create GPU texture. */
eGPUTextureFormat format = (channels == 3) ? GPU_RGB16F : GPU_R16F;
cache_grid->texture = GPU_texture_create_3d(
- "volume_grid", UNPACK3(resolution), 1, format, voxels);
+ "volume_grid", UNPACK3(resolution), 1, format, GPU_DATA_FLOAT, voxels);
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
GPU_texture_wrap_mode(cache_grid->texture, false, false);
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index e3967678319..17db02d986f 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -196,6 +196,8 @@ void DRW_hair_free(void);
void DRW_smoke_ensure(struct FluidModifierData *fmd, int highres);
void DRW_smoke_ensure_coba_field(struct FluidModifierData *fmd);
void DRW_smoke_ensure_velocity(struct FluidModifierData *fmd);
+void DRW_fluid_ensure_flags(struct FluidModifierData *fmd);
+void DRW_fluid_ensure_range_field(struct FluidModifierData *fmd);
void DRW_smoke_free(struct FluidModifierData *fmd);
void DRW_smoke_free_velocity(struct FluidModifierData *fmd);
diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c
index 809512bd7dd..d9bd94b480e 100644
--- a/source/blender/draw/intern/draw_fluid.c
+++ b/source/blender/draw/intern/draw_fluid.c
@@ -177,8 +177,9 @@ static float *rescale_3d(const int dim[3],
/* Will resize input to fit GL system limits. */
static GPUTexture *create_volume_texture(const int dim[3],
- eGPUTextureFormat format,
- const float *data)
+ eGPUTextureFormat texture_format,
+ eGPUDataFormat data_format,
+ const void *data)
{
GPUTexture *tex = NULL;
int final_dim[3] = {UNPACK3(dim)};
@@ -188,7 +189,8 @@ static GPUTexture *create_volume_texture(const int dim[3],
}
while (1) {
- tex = GPU_texture_create_3d("volume", UNPACK3(final_dim), 1, format, NULL);
+ tex = GPU_texture_create_3d(
+ "volume", UNPACK3(final_dim), 1, texture_format, data_format, NULL);
if (tex != NULL) {
break;
@@ -209,11 +211,15 @@ static GPUTexture *create_volume_texture(const int dim[3],
}
else if (equals_v3v3_int(dim, final_dim)) {
/* No need to resize, just upload the data. */
- GPU_texture_update_sub(tex, GPU_DATA_FLOAT, data, 0, 0, 0, UNPACK3(final_dim));
+ GPU_texture_update_sub(tex, data_format, data, 0, 0, 0, UNPACK3(final_dim));
+ }
+ else if (data_format != GPU_DATA_FLOAT) {
+ printf("Error: Could not allocate 3D texture and not attempting to rescale non-float data.\n");
+ tex = GPU_texture_create_error(3, false);
}
else {
/* We need to resize the input. */
- int channels = (format == GPU_R8) ? 1 : 4;
+ int channels = (ELEM(texture_format, GPU_R8, GPU_R16F, GPU_R32F)) ? 1 : 4;
float *rescaled_data = rescale_3d(dim, final_dim, channels, data);
if (rescaled_data) {
GPU_texture_update_sub(tex, GPU_DATA_FLOAT, rescaled_data, 0, 0, 0, UNPACK3(final_dim));
@@ -228,9 +234,15 @@ static GPUTexture *create_volume_texture(const int dim[3],
return tex;
}
-static GPUTexture *create_field_texture(FluidDomainSettings *fds)
+static GPUTexture *create_field_texture(FluidDomainSettings *fds, bool single_precision)
{
- float *field = NULL;
+ void *field = NULL;
+ eGPUDataFormat data_format = GPU_DATA_FLOAT;
+ eGPUTextureFormat texture_format = GPU_R8;
+
+ if (single_precision) {
+ texture_format = GPU_R32F;
+ }
switch (fds->coba_field) {
case FLUID_DOMAIN_FIELD_DENSITY:
@@ -275,11 +287,36 @@ static GPUTexture *create_field_texture(FluidDomainSettings *fds)
case FLUID_DOMAIN_FIELD_FORCE_Z:
field = manta_get_force_z(fds->fluid);
break;
+ case FLUID_DOMAIN_FIELD_PHI:
+ field = manta_get_phi(fds->fluid);
+ texture_format = GPU_R16F;
+ break;
+ case FLUID_DOMAIN_FIELD_PHI_IN:
+ field = manta_get_phi_in(fds->fluid);
+ texture_format = GPU_R16F;
+ break;
+ case FLUID_DOMAIN_FIELD_PHI_OUT:
+ field = manta_get_phiout_in(fds->fluid);
+ texture_format = GPU_R16F;
+ break;
+ case FLUID_DOMAIN_FIELD_PHI_OBSTACLE:
+ field = manta_get_phiobs_in(fds->fluid);
+ texture_format = GPU_R16F;
+ break;
+ case FLUID_DOMAIN_FIELD_FLAGS:
+ field = manta_smoke_get_flags(fds->fluid);
+ data_format = GPU_DATA_INT;
+ texture_format = GPU_R8UI;
+ break;
+ case FLUID_DOMAIN_FIELD_PRESSURE:
+ field = manta_get_pressure(fds->fluid);
+ texture_format = GPU_R16F;
+ break;
default:
return NULL;
}
- GPUTexture *tex = create_volume_texture(fds->res, GPU_R8, field);
+ GPUTexture *tex = create_volume_texture(fds->res, texture_format, data_format, field);
swizzle_texture_channel_single(tex);
return tex;
}
@@ -300,7 +337,7 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres)
return NULL;
}
- GPUTexture *tex = create_volume_texture(dim, GPU_R8, data);
+ GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, data);
swizzle_texture_channel_single(tex);
return tex;
}
@@ -329,7 +366,7 @@ static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres)
manta_smoke_get_rgba(fds->fluid, data, 0);
}
- GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, data);
+ GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, GPU_DATA_FLOAT, data);
MEM_freeN(data);
@@ -354,11 +391,38 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres)
source = manta_smoke_get_flame(fds->fluid);
}
- GPUTexture *tex = create_volume_texture(dim, GPU_R8, source);
+ GPUTexture *tex = create_volume_texture(dim, GPU_R8, GPU_DATA_FLOAT, source);
swizzle_texture_channel_single(tex);
return tex;
}
+static bool get_smoke_velocity_field(FluidDomainSettings *fds,
+ float **r_velocity_x,
+ float **r_velocity_y,
+ float **r_velocity_z)
+{
+ const char vector_field = fds->vector_field;
+ switch ((FLUID_DisplayVectorField)vector_field) {
+ case FLUID_DOMAIN_VECTOR_FIELD_VELOCITY:
+ *r_velocity_x = manta_get_velocity_x(fds->fluid);
+ *r_velocity_y = manta_get_velocity_y(fds->fluid);
+ *r_velocity_z = manta_get_velocity_z(fds->fluid);
+ break;
+ case FLUID_DOMAIN_VECTOR_FIELD_GUIDE_VELOCITY:
+ *r_velocity_x = manta_get_guide_velocity_x(fds->fluid);
+ *r_velocity_y = manta_get_guide_velocity_y(fds->fluid);
+ *r_velocity_z = manta_get_guide_velocity_z(fds->fluid);
+ break;
+ case FLUID_DOMAIN_VECTOR_FIELD_FORCE:
+ *r_velocity_x = manta_get_force_x(fds->fluid);
+ *r_velocity_y = manta_get_force_y(fds->fluid);
+ *r_velocity_z = manta_get_force_z(fds->fluid);
+ break;
+ }
+
+ return *r_velocity_x && *r_velocity_y && *r_velocity_z;
+}
+
#endif /* WITH_FLUID */
/** \} */
@@ -416,9 +480,15 @@ void DRW_smoke_ensure_coba_field(FluidModifierData *fmd)
FluidDomainSettings *fds = fmd->domain;
if (!fds->tex_field) {
- fds->tex_field = create_field_texture(fds);
+ fds->tex_field = create_field_texture(fds, false);
}
- if (!fds->tex_coba) {
+ if (!fds->tex_coba && !ELEM(fds->coba_field,
+ FLUID_DOMAIN_FIELD_PHI,
+ FLUID_DOMAIN_FIELD_PHI_IN,
+ FLUID_DOMAIN_FIELD_PHI_OUT,
+ FLUID_DOMAIN_FIELD_PHI_OBSTACLE,
+ FLUID_DOMAIN_FIELD_FLAGS,
+ FLUID_DOMAIN_FIELD_PRESSURE)) {
fds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, fds->coba);
}
}
@@ -447,7 +517,7 @@ void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
}
if (!fds->tex_shadow) {
fds->tex_shadow = create_volume_texture(
- fds->res, GPU_R8, manta_smoke_get_shadow(fds->fluid));
+ fds->res, GPU_R8, GPU_DATA_FLOAT, manta_smoke_get_shadow(fds->fluid));
}
}
#endif /* WITH_FLUID */
@@ -460,25 +530,62 @@ void DRW_smoke_ensure_velocity(FluidModifierData *fmd)
#else
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
FluidDomainSettings *fds = fmd->domain;
+ float *vel_x = NULL, *vel_y = NULL, *vel_z = NULL;
- const float *vel_x = manta_get_velocity_x(fds->fluid);
- const float *vel_y = manta_get_velocity_y(fds->fluid);
- const float *vel_z = manta_get_velocity_z(fds->fluid);
+ if (!get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z)) {
+ fds->vector_field = FLUID_DOMAIN_VECTOR_FIELD_VELOCITY;
+ get_smoke_velocity_field(fds, &vel_x, &vel_y, &vel_z);
+ }
if (ELEM(NULL, vel_x, vel_y, vel_z)) {
return;
}
if (!fds->tex_velocity_x) {
- fds->tex_velocity_x = GPU_texture_create_3d("velx", UNPACK3(fds->res), 1, GPU_R16F, vel_x);
- fds->tex_velocity_y = GPU_texture_create_3d("vely", UNPACK3(fds->res), 1, GPU_R16F, vel_y);
- fds->tex_velocity_z = GPU_texture_create_3d("velz", UNPACK3(fds->res), 1, GPU_R16F, vel_z);
+ fds->tex_velocity_x = GPU_texture_create_3d(
+ "velx", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_x);
+ fds->tex_velocity_y = GPU_texture_create_3d(
+ "vely", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_y);
+ fds->tex_velocity_z = GPU_texture_create_3d(
+ "velz", UNPACK3(fds->res), 1, GPU_R16F, GPU_DATA_FLOAT, vel_z);
}
}
#endif /* WITH_FLUID */
}
-/* TODO Unify with the other DRW_smoke_free. */
+void DRW_fluid_ensure_flags(FluidModifierData *fmd)
+{
+#ifndef WITH_FLUID
+ UNUSED_VARS(fmd);
+#else
+ if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ FluidDomainSettings *fds = fmd->domain;
+ if (!fds->tex_flags) {
+ fds->tex_flags = create_volume_texture(
+ fds->res, GPU_R8UI, GPU_DATA_INT, manta_smoke_get_flags(fds->fluid));
+
+ swizzle_texture_channel_single(fds->tex_flags);
+ }
+ }
+#endif /* WITH_FLUID */
+}
+
+void DRW_fluid_ensure_range_field(FluidModifierData *fmd)
+{
+#ifndef WITH_FLUID
+ UNUSED_VARS(fmd);
+#else
+ if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ FluidDomainSettings *fds = fmd->domain;
+
+ if (!fds->tex_range_field) {
+ fds->tex_range_field = create_field_texture(fds, true);
+ }
+ }
+#endif /* WITH_FLUID */
+}
+
+/* TODO Unify with the other GPU_free_smoke. */
void DRW_smoke_free_velocity(FluidModifierData *fmd)
{
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
@@ -494,9 +601,19 @@ void DRW_smoke_free_velocity(FluidModifierData *fmd)
GPU_texture_free(fmd->domain->tex_velocity_z);
}
+ if (fmd->domain->tex_flags) {
+ GPU_texture_free(fmd->domain->tex_flags);
+ }
+
+ if (fmd->domain->tex_range_field) {
+ GPU_texture_free(fmd->domain->tex_range_field);
+ }
+
fmd->domain->tex_velocity_x = NULL;
fmd->domain->tex_velocity_y = NULL;
fmd->domain->tex_velocity_z = NULL;
+ fmd->domain->tex_flags = NULL;
+ fmd->domain->tex_range_field = NULL;
}
}
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 8562a5ba8fb..a456aa9916e 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -112,7 +112,8 @@ GPUTexture *DRW_texture_create_3d(
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_3d(__func__, w, h, d, mips, format, fpixels);
+ GPUTexture *tex = GPU_texture_create_3d(
+ __func__, w, h, d, mips, format, GPU_DATA_FLOAT, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc
index f99fa04ce75..cb9a572eadf 100644
--- a/source/blender/draw/tests/shaders_test.cc
+++ b/source/blender/draw/tests/shaders_test.cc
@@ -97,22 +97,53 @@ TEST_F(DrawTest, workbench_glsl_shaders)
EXPECT_NE(workbench_shader_antialiasing_get(1), nullptr);
EXPECT_NE(workbench_shader_antialiasing_get(2), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, false, false, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, false, false, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, false, true, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, false, true, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, true, false, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, true, false, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, true, true, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(false, true, true, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, false, false, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, false, false, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, false, true, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, false, true, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, true, false, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, true, false, true), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, true, true, false), nullptr);
- EXPECT_NE(workbench_shader_volume_get(true, true, true, true), nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_LINEAR, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_LINEAR, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_CUBIC, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_CUBIC, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_CLOSEST, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, false, WORKBENCH_VOLUME_INTERP_CLOSEST, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_LINEAR, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_LINEAR, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_CUBIC, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_CUBIC, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_CLOSEST, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(false, true, WORKBENCH_VOLUME_INTERP_CLOSEST, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_LINEAR, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_LINEAR, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_CUBIC, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_CUBIC, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_CLOSEST, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, false, WORKBENCH_VOLUME_INTERP_CLOSEST, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_LINEAR, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_LINEAR, true),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_CUBIC, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_CUBIC, true), nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_CLOSEST, false),
+ nullptr);
+ EXPECT_NE(workbench_shader_volume_get(true, true, WORKBENCH_VOLUME_INTERP_CLOSEST, true),
+ nullptr);
GPUShader *dof_prepare_sh;
GPUShader *dof_downsample_sh;