diff options
Diffstat (limited to 'source')
25 files changed, 1289 insertions, 197 deletions
diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h index 88a5492d85b..87e1c7a57ed 100644 --- a/source/blender/blenkernel/BKE_fluid.h +++ b/source/blender/blenkernel/BKE_fluid.h @@ -93,6 +93,7 @@ void BKE_fluid_flow_type_set(struct Object *object, struct FluidFlowSettings *se void BKE_fluid_effector_type_set(struct Object *object, struct FluidEffectorSettings *settings, int type); +void BKE_fluid_coba_field_sanitize(struct FluidDomainSettings *settings); void BKE_fluid_flow_behavior_set(struct Object *object, struct FluidFlowSettings *settings, int behavior); diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index df7d308a87c..98488bb46d8 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -4682,6 +4682,30 @@ void BKE_fluid_effector_type_set(Object *UNUSED(object), FluidEffectorSettings * settings->type = type; } +void BKE_fluid_coba_field_sanitize(FluidDomainSettings *settings) +{ + /* Based on the domain type, the coba field is defaulted accordingly if the selected field + * is unsupported. */ + const char field = settings->coba_field; + + if (settings->type == FLUID_DOMAIN_TYPE_GAS) { + if (field == FLUID_DOMAIN_FIELD_PHI || field == FLUID_DOMAIN_FIELD_PHI_IN || + field == FLUID_DOMAIN_FIELD_PHI_OUT || field == FLUID_DOMAIN_FIELD_PHI_OBSTACLE) { + /* Defaulted to density for gas domain. */ + settings->coba_field = FLUID_DOMAIN_FIELD_DENSITY; + } + } + else if (settings->type == FLUID_DOMAIN_TYPE_LIQUID) { + if (field == FLUID_DOMAIN_FIELD_COLOR_R || field == FLUID_DOMAIN_FIELD_COLOR_G || + field == FLUID_DOMAIN_FIELD_COLOR_B || field == FLUID_DOMAIN_FIELD_DENSITY || + field == FLUID_DOMAIN_FIELD_FLAME || field == FLUID_DOMAIN_FIELD_FUEL || + field == FLUID_DOMAIN_FIELD_HEAT) { + /* Defaulted to phi for liquid domain. */ + settings->coba_field = FLUID_DOMAIN_FIELD_PHI; + } + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -4980,19 +5004,32 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *fmd) fmd->domain->timesteps_maximum = 4; /* display options */ - fmd->domain->slice_method = FLUID_DOMAIN_SLICE_VIEW_ALIGNED; fmd->domain->axis_slice_method = AXIS_SLICE_FULL; fmd->domain->slice_axis = 0; - fmd->domain->interp_method = 0; + fmd->domain->interp_method = FLUID_DISPLAY_INTERP_LINEAR; fmd->domain->draw_velocity = false; fmd->domain->slice_per_voxel = 5.0f; fmd->domain->slice_depth = 0.5f; fmd->domain->display_thickness = 1.0f; + fmd->domain->show_gridlines = false; fmd->domain->coba = NULL; + fmd->domain->grid_scale = 1.0f; fmd->domain->vector_scale = 1.0f; fmd->domain->vector_draw_type = VECTOR_DRAW_NEEDLE; + fmd->domain->vector_field = FLUID_DOMAIN_VECTOR_FIELD_VELOCITY; + fmd->domain->vector_scale_with_magnitude = true; + fmd->domain->vector_draw_mac_components = VECTOR_DRAW_MAC_X | VECTOR_DRAW_MAC_Y | + VECTOR_DRAW_MAC_Z; fmd->domain->use_coba = false; fmd->domain->coba_field = FLUID_DOMAIN_FIELD_DENSITY; + fmd->domain->gridlines_color_field = 0; + fmd->domain->gridlines_lower_bound = 0.0f; + fmd->domain->gridlines_upper_bound = 1.0f; + fmd->domain->gridlines_range_color[0] = 1.0f; + fmd->domain->gridlines_range_color[1] = 0.0f; + fmd->domain->gridlines_range_color[2] = 0.0f; + fmd->domain->gridlines_range_color[3] = 1.0f; + fmd->domain->gridlines_cell_filter = FLUID_CELL_TYPE_NONE; /* -- Deprecated / unsed options (below)-- */ @@ -5219,7 +5256,6 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->timesteps_maximum = fds->timesteps_maximum; /* display options */ - tfds->slice_method = fds->slice_method; tfds->axis_slice_method = fds->axis_slice_method; tfds->slice_axis = fds->slice_axis; tfds->interp_method = fds->interp_method; @@ -5227,13 +5263,23 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->slice_per_voxel = fds->slice_per_voxel; tfds->slice_depth = fds->slice_depth; tfds->display_thickness = fds->display_thickness; + tfds->show_gridlines = fds->show_gridlines; if (fds->coba) { tfds->coba = MEM_dupallocN(fds->coba); } tfds->vector_scale = fds->vector_scale; tfds->vector_draw_type = fds->vector_draw_type; + tfds->vector_field = fds->vector_field; + tfds->vector_scale_with_magnitude = fds->vector_scale_with_magnitude; + tfds->vector_draw_mac_components = fds->vector_draw_mac_components; tfds->use_coba = fds->use_coba; tfds->coba_field = fds->coba_field; + tfds->grid_scale = fds->grid_scale; + tfds->gridlines_color_field = fds->gridlines_color_field; + tfds->gridlines_lower_bound = fds->gridlines_lower_bound; + tfds->gridlines_upper_bound = fds->gridlines_upper_bound; + copy_v4_v4(tfds->gridlines_range_color, fds->gridlines_range_color); + tfds->gridlines_cell_filter = fds->gridlines_cell_filter; /* -- Deprecated / unsed options (below)-- */ 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; diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 99a7c6a5f0c..862da60c845 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -199,8 +199,14 @@ GPUTexture *GPU_texture_create_2d( const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data); GPUTexture *GPU_texture_create_2d_array( const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data); -GPUTexture *GPU_texture_create_3d( - const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data); +GPUTexture *GPU_texture_create_3d(const char *name, + int w, + int h, + int d, + int mips, + eGPUTextureFormat texture_format, + eGPUDataFormat data_format, + const void *data); GPUTexture *GPU_texture_create_cube( const char *name, int w, int mips, eGPUTextureFormat format, const float *data); GPUTexture *GPU_texture_create_cube_array( diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index eb6881164b2..f7f29c7cece 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -199,7 +199,8 @@ static inline GPUTexture *gpu_texture_create(const char *name, const eGPUTextureType type, int UNUSED(mips), eGPUTextureFormat tex_format, - const float *fpixels) + eGPUDataFormat data_format, + const void *pixels) { Texture *tex = GPUBackend::get()->texture_alloc(name); bool success = false; @@ -227,8 +228,8 @@ static inline GPUTexture *gpu_texture_create(const char *name, delete tex; return NULL; } - if (fpixels) { - tex->update(GPU_DATA_FLOAT, fpixels); + if (pixels) { + tex->update(data_format, pixels); } return reinterpret_cast<GPUTexture *>(tex); } @@ -236,43 +237,53 @@ static inline GPUTexture *gpu_texture_create(const char *name, GPUTexture *GPU_texture_create_1d( const char *name, int w, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, 0, 0, GPU_TEXTURE_1D, mips, format, data); + return gpu_texture_create(name, w, 0, 0, GPU_TEXTURE_1D, mips, format, GPU_DATA_FLOAT, data); } GPUTexture *GPU_texture_create_1d_array( const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, h, 0, GPU_TEXTURE_1D_ARRAY, mips, format, data); + return gpu_texture_create( + name, w, h, 0, GPU_TEXTURE_1D_ARRAY, mips, format, GPU_DATA_FLOAT, data); } GPUTexture *GPU_texture_create_2d( const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, h, 0, GPU_TEXTURE_2D, mips, format, data); + return gpu_texture_create(name, w, h, 0, GPU_TEXTURE_2D, mips, format, GPU_DATA_FLOAT, data); } GPUTexture *GPU_texture_create_2d_array( const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, h, d, GPU_TEXTURE_2D_ARRAY, mips, format, data); + return gpu_texture_create( + name, w, h, d, GPU_TEXTURE_2D_ARRAY, mips, format, GPU_DATA_FLOAT, data); } -GPUTexture *GPU_texture_create_3d( - const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data) +GPUTexture *GPU_texture_create_3d(const char *name, + int w, + int h, + int d, + int mips, + eGPUTextureFormat texture_format, + eGPUDataFormat data_format, + const void *data) { - return gpu_texture_create(name, w, h, d, GPU_TEXTURE_3D, mips, format, data); + return gpu_texture_create( + name, w, h, d, GPU_TEXTURE_3D, mips, texture_format, data_format, data); } GPUTexture *GPU_texture_create_cube( const char *name, int w, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, w, 0, GPU_TEXTURE_CUBE, mips, format, data); + return gpu_texture_create(name, w, w, 0, GPU_TEXTURE_CUBE, mips, format, GPU_DATA_FLOAT, data); } GPUTexture *GPU_texture_create_cube_array( const char *name, int w, int d, int mips, eGPUTextureFormat format, const float *data) { - return gpu_texture_create(name, w, w, d, GPU_TEXTURE_CUBE_ARRAY, mips, format, data); + return gpu_texture_create( + name, w, w, d, GPU_TEXTURE_CUBE_ARRAY, mips, format, GPU_DATA_FLOAT, data); } /* DDS texture loading. Return NULL if support is not available. */ @@ -326,7 +337,7 @@ GPUTexture *GPU_texture_create_error(int dimension, bool is_array) type = (dimension == 2) ? (is_array ? GPU_TEXTURE_2D_ARRAY : GPU_TEXTURE_2D) : type; type = (dimension == 1) ? (is_array ? GPU_TEXTURE_1D_ARRAY : GPU_TEXTURE_1D) : type; - return gpu_texture_create("invalid_tex", w, h, d, type, 1, GPU_RGBA8, pixel); + return gpu_texture_create("invalid_tex", w, h, d, type, 1, GPU_RGBA8, GPU_DATA_FLOAT, pixel); } /* ------ Update ------ */ diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index 6035c43ad57..8e7f3471e1e 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -66,12 +66,6 @@ enum { FLUID_DOMAIN_FILE_BIN_OBJECT = (1 << 4), }; -/* Slice method. */ -enum { - FLUID_DOMAIN_SLICE_VIEW_ALIGNED = 0, - FLUID_DOMAIN_SLICE_AXIS_ALIGNED = 1, -}; - /* Axis aligned method. */ enum { AXIS_SLICE_FULL = 0, @@ -86,17 +80,32 @@ enum { SLICE_AXIS_Z = 3, }; -/* Axis aligned method. */ -enum { - VOLUME_INTERP_LINEAR = 0, - VOLUME_INTERP_CUBIC = 1, -}; +/* Display interpolation method. */ +typedef enum FLUID_DisplayInterpolationMethod { + FLUID_DISPLAY_INTERP_LINEAR = 0, + FLUID_DISPLAY_INTERP_CUBIC = 1, + FLUID_DISPLAY_INTERP_CLOSEST = 2, +} FLUID_DisplayInterpolationMethod; enum { VECTOR_DRAW_NEEDLE = 0, VECTOR_DRAW_STREAMLINE = 1, + VECTOR_DRAW_MAC = 2, +}; + +enum { + VECTOR_DRAW_MAC_X = (1 << 0), + VECTOR_DRAW_MAC_Y = (1 << 1), + VECTOR_DRAW_MAC_Z = (1 << 2), }; +/* Fluid domain vector fields. */ +typedef enum FLUID_DisplayVectorField { + FLUID_DOMAIN_VECTOR_FIELD_VELOCITY = 0, + FLUID_DOMAIN_VECTOR_FIELD_GUIDE_VELOCITY = 1, + FLUID_DOMAIN_VECTOR_FIELD_FORCE = 2, +} FLUID_DisplayVectorField; + enum { SNDPARTICLE_BOUNDARY_DELETE = 0, SNDPARTICLE_BOUNDARY_PUSHOUT = 1, @@ -125,6 +134,28 @@ enum { FLUID_DOMAIN_FIELD_FORCE_X = 11, FLUID_DOMAIN_FIELD_FORCE_Y = 12, FLUID_DOMAIN_FIELD_FORCE_Z = 13, + FLUID_DOMAIN_FIELD_PHI = 14, + FLUID_DOMAIN_FIELD_PHI_IN = 15, + FLUID_DOMAIN_FIELD_PHI_OUT = 16, + FLUID_DOMAIN_FIELD_PHI_OBSTACLE = 17, + FLUID_DOMAIN_FIELD_FLAGS = 18, + FLUID_DOMAIN_FIELD_PRESSURE = 19, +}; + +/* Fluid gridline display color field types. */ +enum { + FLUID_GRIDLINE_COLOR_TYPE_FLAGS = 1, + FLUID_GRIDLINE_COLOR_TYPE_RANGE = 2, +}; + +/* Fluid cell types. */ +enum { + FLUID_CELL_TYPE_NONE = 0, + FLUID_CELL_TYPE_FLUID = (1 << 0), + FLUID_CELL_TYPE_OBSTACLE = (1 << 1), + FLUID_CELL_TYPE_EMPTY = (1 << 2), + FLUID_CELL_TYPE_INFLOW = (1 << 3), + FLUID_CELL_TYPE_OUTFLOW = (1 << 4), }; /* Fluid domain types. */ @@ -446,6 +477,8 @@ typedef struct FluidDomainSettings { struct GPUTexture *tex_velocity_x; struct GPUTexture *tex_velocity_y; struct GPUTexture *tex_velocity_z; + struct GPUTexture *tex_flags; + struct GPUTexture *tex_range_field; struct Object *guide_parent; /** Vertex velocities of simulated fluid mesh. */ struct FluidDomainVertexVelocity *mesh_velocities; @@ -605,29 +638,41 @@ typedef struct FluidDomainSettings { int timesteps_maximum; /* Display options. */ - char slice_method, axis_slice_method; - char slice_axis, draw_velocity; float slice_per_voxel; float slice_depth; float display_thickness; + float grid_scale; struct ColorBand *coba; float vector_scale; + float gridlines_lower_bound; + float gridlines_upper_bound; + float gridlines_range_color[4]; + char axis_slice_method; + char slice_axis; + char show_gridlines; + char draw_velocity; char vector_draw_type; + char vector_field; /* Simulation field used for vector display. */ + char vector_scale_with_magnitude; + char vector_draw_mac_components; char use_coba; char coba_field; /* Simulation field used for the color mapping. */ char interp_method; + char gridlines_color_field; /* Simulation field used to color map onto gridlines. */ + char gridlines_cell_filter; + char _pad9[7]; /* OpenVDB cache options. */ int openvdb_compression; float clipping; char openvdb_data_depth; - char _pad9[7]; /* Unused. */ + char _pad10[7]; /* Unused. */ /* -- Deprecated / unsed options (below). -- */ /* View options. */ int viewsettings; - char _pad10[4]; /* Unused. */ + char _pad11[4]; /* Unused. */ /* Pointcache options. */ /* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading @@ -637,7 +682,7 @@ typedef struct FluidDomainSettings { int cache_comp; int cache_high_comp; char cache_file_format; - char _pad11[7]; /* Unused. */ + char _pad12[7]; /* Unused. */ } FluidDomainSettings; diff --git a/source/blender/makesdna/DNA_volume_defaults.h b/source/blender/makesdna/DNA_volume_defaults.h index 8239f263c6c..a710754659b 100644 --- a/source/blender/makesdna/DNA_volume_defaults.h +++ b/source/blender/makesdna/DNA_volume_defaults.h @@ -32,6 +32,7 @@ .density = 1.0f, \ .wireframe_type = VOLUME_WIREFRAME_BOXES, \ .wireframe_detail = VOLUME_WIREFRAME_COARSE, \ + .slice_depth = 0.5f, \ } #define _DNA_DEFAULT_VolumeRender \ diff --git a/source/blender/makesdna/DNA_volume_types.h b/source/blender/makesdna/DNA_volume_types.h index 30ac67281e2..bbd23298aea 100644 --- a/source/blender/makesdna/DNA_volume_types.h +++ b/source/blender/makesdna/DNA_volume_types.h @@ -38,6 +38,10 @@ typedef struct VolumeDisplay { float density; int wireframe_type; int wireframe_detail; + int interpolation_method; + int axis_slice_method; + int slice_axis; + float slice_depth; int _pad[1]; } VolumeDisplay; @@ -119,5 +123,26 @@ typedef enum VolumeRenderSpace { VOLUME_SPACE_WORLD = 1, } VolumeRenderSpace; +/* VolumeDisplay.interpolation_method */ +typedef enum VolumeDisplayInterpMethod { + VOLUME_DISPLAY_INTERP_LINEAR = 0, + VOLUME_DISPLAY_INTERP_CUBIC = 1, + VOLUME_DISPLAY_INTERP_CLOSEST = 2, +} VolumeDisplayInterpMethod; + +/* VolumeDisplay.axis_slice_method */ +typedef enum AxisAlignedSlicingMethod { + VOLUME_AXIS_SLICE_FULL = 0, + VOLUME_AXIS_SLICE_SINGLE = 1, +} AxisAlignedSlicingMethod; + +/* VolumeDisplay.slice_axis */ +typedef enum SliceAxis { + VOLUME_SLICE_AXIS_AUTO = 0, + VOLUME_SLICE_AXIS_X = 1, + VOLUME_SLICE_AXIS_Y = 2, + VOLUME_SLICE_AXIS_Z = 3, +} SliceAxis; + /* Only one material supported currently. */ #define VOLUME_MATERIAL_NR 1 diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 2d26317c00b..221eedfe149 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -670,6 +670,7 @@ static void rna_Fluid_domaintype_set(struct PointerRNA *ptr, int value) FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; Object *ob = (Object *)ptr->owner_id; BKE_fluid_domain_type_set(ob, settings, value); + BKE_fluid_coba_field_sanitize(settings); } static char *rna_FluidDomainSettings_path(PointerRNA *ptr) @@ -1041,6 +1042,159 @@ static void rna_Fluid_flowtype_set(struct PointerRNA *ptr, int value) } } +static const EnumPropertyItem *rna_Fluid_cobafield_itemf(bContext *UNUSED(C), + PointerRNA *ptr, + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + + EnumPropertyItem *item = NULL; + EnumPropertyItem tmp = {0, "", 0, "", ""}; + int totitem = 0; + + tmp.value = FLUID_DOMAIN_FIELD_FLAGS; + tmp.identifier = "FLAGS"; + tmp.icon = 0; + tmp.name = "Flags"; + tmp.description = "Flag grid of the fluid domain"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_PRESSURE; + tmp.identifier = "PRESSURE"; + tmp.icon = 0; + tmp.name = "Pressure"; + tmp.description = "Pressure field of the fluid domain"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_VELOCITY_X; + tmp.identifier = "VELOCITY_X"; + tmp.icon = 0; + tmp.name = "X Velocity"; + tmp.description = "X component of the velocity field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_VELOCITY_Y; + tmp.identifier = "VELOCITY_Y"; + tmp.icon = 0; + tmp.name = "Y Velocity"; + tmp.description = "Y component of the velocity field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_VELOCITY_Z; + tmp.identifier = "VELOCITY_Z"; + tmp.icon = 0; + tmp.name = "Z Velocity"; + tmp.description = "Z component of the velocity field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_FORCE_X; + tmp.identifier = "FORCE_X"; + tmp.icon = 0; + tmp.name = "X Force"; + tmp.description = "X component of the force field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_FORCE_Y; + tmp.identifier = "FORCE_Y"; + tmp.icon = 0; + tmp.name = "Y Force"; + tmp.description = "Y component of the force field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_FORCE_Z; + tmp.identifier = "FORCE_Z"; + tmp.icon = 0; + tmp.name = "Z Force"; + tmp.description = "Z component of the force field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + if (settings->type == FLUID_DOMAIN_TYPE_GAS) { + tmp.value = FLUID_DOMAIN_FIELD_COLOR_R; + tmp.identifier = "COLOR_R"; + tmp.icon = 0; + tmp.name = "Red"; + tmp.description = "Red component of the color field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_COLOR_G; + tmp.identifier = "COLOR_G"; + tmp.icon = 0; + tmp.name = "Green"; + tmp.description = "Green component of the color field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_COLOR_B; + tmp.identifier = "COLOR_B"; + tmp.icon = 0; + tmp.name = "Blue"; + tmp.description = "Blue component of the color field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_DENSITY; + tmp.identifier = "DENSITY"; + tmp.icon = 0; + tmp.name = "Density"; + tmp.description = "Quantity of soot in the fluid"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_FLAME; + tmp.identifier = "FLAME"; + tmp.icon = 0; + tmp.name = "Flame"; + tmp.description = "Flame field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_FUEL; + tmp.identifier = "FUEL"; + tmp.icon = 0; + tmp.name = "Fuel"; + tmp.description = "Fuel field"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_HEAT; + tmp.identifier = "HEAT"; + tmp.icon = 0; + tmp.name = "Heat"; + tmp.description = "Temperature of the fluid"; + RNA_enum_item_add(&item, &totitem, &tmp); + } + else if (settings->type == FLUID_DOMAIN_TYPE_LIQUID) { + tmp.value = FLUID_DOMAIN_FIELD_PHI; + tmp.identifier = "PHI"; + tmp.icon = 0; + tmp.name = "Fluid Levelset"; + tmp.description = "Levelset representation of the fluid"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_PHI_IN; + tmp.identifier = "PHI_IN"; + tmp.icon = 0; + tmp.name = "Inflow Levelset"; + tmp.description = "Levelset representation of the inflow"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_PHI_OUT; + tmp.identifier = "PHI_OUT"; + tmp.icon = 0; + tmp.name = "Outflow Levelset"; + tmp.description = "Levelset representation of the outflow"; + RNA_enum_item_add(&item, &totitem, &tmp); + + tmp.value = FLUID_DOMAIN_FIELD_PHI_OBSTACLE; + tmp.identifier = "PHI_OBSTACLE"; + tmp.icon = 0; + tmp.name = "Obstacle Levelset"; + tmp.description = "Levelset representation of the obstacles"; + RNA_enum_item_add(&item, &totitem, &tmp); + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + #else static void rna_def_fluid_mesh_vertices(BlenderRNA *brna) @@ -1152,20 +1306,6 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - static const EnumPropertyItem view_items[] = { - {FLUID_DOMAIN_SLICE_VIEW_ALIGNED, - "VIEW_ALIGNED", - 0, - "View", - "Slice volume parallel to the view plane"}, - {FLUID_DOMAIN_SLICE_AXIS_ALIGNED, - "AXIS_ALIGNED", - 0, - "Axis", - "Slice volume parallel to the major axis"}, - {0, NULL, 0, NULL, NULL}, - }; - static const EnumPropertyItem axis_slice_method_items[] = { {AXIS_SLICE_FULL, "FULL", 0, "Full", "Slice the whole domain object"}, {AXIS_SLICE_SINGLE, "SINGLE", 0, "Single", "Perform a single slice of the domain object"}, @@ -1173,12 +1313,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) }; static const EnumPropertyItem interp_method_item[] = { - {VOLUME_INTERP_LINEAR, "LINEAR", 0, "Linear", "Good smoothness and speed"}, - {VOLUME_INTERP_CUBIC, + {FLUID_DISPLAY_INTERP_LINEAR, "LINEAR", 0, "Linear", "Good smoothness and speed"}, + {FLUID_DISPLAY_INTERP_CUBIC, "CUBIC", 0, "Cubic", "Smoothed high quality interpolation, but slower"}, + {FLUID_DISPLAY_INTERP_CLOSEST, "CLOSEST", 0, "Closest", "No interpolation"}, {0, NULL, 0, NULL, NULL}, }; @@ -1197,6 +1338,51 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) static const EnumPropertyItem vector_draw_items[] = { {VECTOR_DRAW_NEEDLE, "NEEDLE", 0, "Needle", "Display vectors as needles"}, {VECTOR_DRAW_STREAMLINE, "STREAMLINE", 0, "Streamlines", "Display vectors as streamlines"}, + {VECTOR_DRAW_MAC, "MAC", 0, "MAC Grid", "Display vector field as MAC grid"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem vector_field_items[] = { + {FLUID_DOMAIN_VECTOR_FIELD_VELOCITY, + "FLUID_VELOCITY", + 0, + "Fluid Velocity", + "Velocity field of the fluid domain"}, + {FLUID_DOMAIN_VECTOR_FIELD_GUIDE_VELOCITY, + "GUIDE_VELOCITY", + 0, + "Guide Velocity", + "Guide velocity field of the fluid domain"}, + {FLUID_DOMAIN_VECTOR_FIELD_FORCE, "FORCE", 0, "Force", "Force field of the fluid domain"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem gridlines_color_field_items[] = { + {0, "NONE", 0, "None", "None"}, + {FLUID_GRIDLINE_COLOR_TYPE_FLAGS, "FLAGS", 0, "Flags", "Flag grid of the fluid domain"}, + {FLUID_GRIDLINE_COLOR_TYPE_RANGE, + "RANGE", + 0, + "Highlight Range", + "Highlight the voxels with values of the color mapped field within the range"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem gridlines_cell_filter_items[] = { + {FLUID_CELL_TYPE_NONE, "NONE", 0, "None", "Highlight the cells regardless of their type"}, + {FLUID_CELL_TYPE_FLUID, "FLUID", 0, "Fluid", "Highlight only the cells of type Fluid"}, + {FLUID_CELL_TYPE_OBSTACLE, + "OBSTACLE", + 0, + "Obstacle", + "Highlight only the cells of type Obstacle"}, + {FLUID_CELL_TYPE_EMPTY, "EMPTY", 0, "Empty", "Highlight only the cells of type Empty"}, + {FLUID_CELL_TYPE_INFLOW, "INFLOW", 0, "Inflow", "Highlight only the cells of type Inflow"}, + {FLUID_CELL_TYPE_OUTFLOW, + "OUTFLOW", + 0, + "Outflow", + "Highlight only the cells of type Outflow"}, {0, NULL, 0, NULL, NULL}, }; @@ -2253,12 +2439,6 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) /* display settings */ - prop = RNA_def_property(srna, "slice_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "slice_method"); - RNA_def_property_enum_items(prop, view_items); - RNA_def_property_ui_text(prop, "View Method", "How to slice the volume for viewport rendering"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - prop = RNA_def_property(srna, "axis_slice_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "axis_slice_method"); RNA_def_property_enum_items(prop, axis_slice_method_items); @@ -2300,10 +2480,14 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Interpolation", "Interpolation method to use for smoke/fire volumes in solid mode"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "show_gridlines", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_gridlines", 0); + RNA_def_property_ui_text(prop, "Gridlines", "Show gridlines"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "show_velocity", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw_velocity", 0); - RNA_def_property_ui_text( - prop, "Display Velocity", "Toggle visualization of the velocity field as needles"); + RNA_def_property_ui_text(prop, "Vector Display", "Visualize vector fields"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "vector_display_type", PROP_ENUM, PROP_NONE); @@ -2312,6 +2496,32 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Display Type", ""); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "vector_field", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "vector_field"); + RNA_def_property_enum_items(prop, vector_field_items); + RNA_def_property_ui_text(prop, "Field", "Vector field to be represented by the display vectors"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_scale_with_magnitude", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "vector_scale_with_magnitude", 0); + RNA_def_property_ui_text(prop, "Magnitude", "Scale vectors with their magnitudes"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_show_mac_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "vector_draw_mac_components", VECTOR_DRAW_MAC_X); + RNA_def_property_ui_text(prop, "X", "Show X-component of MAC Grid"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_show_mac_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "vector_draw_mac_components", VECTOR_DRAW_MAC_Y); + RNA_def_property_ui_text(prop, "Y", "Show Y-component of MAC Grid"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "vector_show_mac_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "vector_draw_mac_components", VECTOR_DRAW_MAC_Z); + RNA_def_property_ui_text(prop, "Z", "Show Z-component of MAC Grid"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "vector_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vector_scale"); RNA_def_property_range(prop, 0.0, 1000.0); @@ -2324,44 +2534,33 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_coba", 0); RNA_def_property_boolean_funcs(prop, NULL, "rna_Fluid_use_color_ramp_set"); - RNA_def_property_ui_text( - prop, - "Use Color Ramp", - "Render a simulation field while mapping its voxels values to the colors of a ramp"); + RNA_def_property_ui_text(prop, + "Grid Display", + "Render a simulation field while mapping its voxels values to the " + "colors of a ramp or using a predefined color code"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + /* Coba field items - generated dynamically based on domain type */ static const EnumPropertyItem coba_field_items[] = { - {FLUID_DOMAIN_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"}, - {FLUID_DOMAIN_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"}, - {FLUID_DOMAIN_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"}, - {FLUID_DOMAIN_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"}, - {FLUID_DOMAIN_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"}, - {FLUID_DOMAIN_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"}, - {FLUID_DOMAIN_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"}, - {FLUID_DOMAIN_FIELD_VELOCITY_X, - "VELOCITY_X", - 0, - "X Velocity", - "X component of the velocity field"}, - {FLUID_DOMAIN_FIELD_VELOCITY_Y, - "VELOCITY_Y", - 0, - "Y Velocity", - "Y component of the velocity field"}, - {FLUID_DOMAIN_FIELD_VELOCITY_Z, - "VELOCITY_Z", - 0, - "Z Velocity", - "Z component of the velocity field"}, + {0, "NONE", 0, "", ""}, {0, NULL, 0, NULL, NULL}, }; - prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "color_ramp_field", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "coba_field"); RNA_def_property_enum_items(prop, coba_field_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Fluid_cobafield_itemf"); RNA_def_property_ui_text(prop, "Field", "Simulation field to color map"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "color_ramp_field_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "grid_scale"); + RNA_def_property_range(prop, 0.001, 100000.0); + RNA_def_property_ui_range(prop, 0.001, 1000.0, 0.1, 3); + RNA_def_property_ui_text( + prop, "Scale", "Multiplier for scaling the selected field to color map"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "coba"); RNA_def_property_struct_type(prop, "ColorRamp"); @@ -2378,6 +2577,39 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Value under which voxels are considered empty space to optimize rendering"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + prop = RNA_def_property(srna, "gridlines_color_field", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gridlines_color_field"); + RNA_def_property_enum_items(prop, gridlines_color_field_items); + RNA_def_property_ui_text( + prop, "Color Gridlines", "Simulation field to color map onto gridlines"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "gridlines_lower_bound", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "gridlines_lower_bound"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Lower Bound", "Lower bound of the highlighting range"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + + prop = RNA_def_property(srna, "gridlines_upper_bound", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "gridlines_upper_bound"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Upper Bound", "Upper bound of the highlighting range"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + + prop = RNA_def_property(srna, "gridlines_range_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "gridlines_range_color"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Color", "Color used to highlight the range"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + + prop = RNA_def_property(srna, "gridlines_cell_filter", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gridlines_cell_filter"); + RNA_def_property_enum_items(prop, gridlines_cell_filter_items); + RNA_def_property_ui_text(prop, "Cell Type", "Cell type to be highlighted"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + /* -- Deprecated / unsed options (below)-- */ /* pointcache options */ diff --git a/source/blender/makesrna/intern/rna_volume.c b/source/blender/makesrna/intern/rna_volume.c index b03d6082cea..054f108099b 100644 --- a/source/blender/makesrna/intern/rna_volume.c +++ b/source/blender/makesrna/intern/rna_volume.c @@ -395,6 +395,39 @@ static void rna_def_volume_display(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem interpolation_method_items[] = { + {VOLUME_DISPLAY_INTERP_LINEAR, "LINEAR", 0, "Linear", "Good smoothness and speed"}, + {VOLUME_DISPLAY_INTERP_CUBIC, + "CUBIC", + 0, + "Cubic", + "Smoothed high quality interpolation, but slower"}, + {VOLUME_DISPLAY_INTERP_CLOSEST, "CLOSEST", 0, "Closest", "No interpolation"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem axis_slice_method_items[] = { + {VOLUME_AXIS_SLICE_FULL, "FULL", 0, "Full", "Slice the whole domain object"}, + {VOLUME_AXIS_SLICE_SINGLE, + "SINGLE", + 0, + "Single", + "Perform a single slice of the domain object"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem axis_slice_position_items[] = { + {VOLUME_SLICE_AXIS_AUTO, + "AUTO", + 0, + "Auto", + "Adjust slice direction according to the view direction"}, + {VOLUME_SLICE_AXIS_X, "X", 0, "X", "Slice along the X axis"}, + {VOLUME_SLICE_AXIS_Y, "Y", 0, "Y", "Slice along the Y axis"}, + {VOLUME_SLICE_AXIS_Z, "Z", 0, "Z", "Slice along the Z axis"}, + {0, NULL, 0, NULL, NULL}, + }; + prop = RNA_def_property(srna, "wireframe_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, wireframe_type_items); RNA_def_property_ui_text(prop, "Wireframe", "Type of wireframe display"); @@ -404,6 +437,27 @@ static void rna_def_volume_display(BlenderRNA *brna) RNA_def_property_enum_items(prop, wireframe_detail_items); RNA_def_property_ui_text(prop, "Wireframe Detail", "Amount of detail for wireframe display"); RNA_def_property_update(prop, 0, "rna_Volume_update_display"); + + prop = RNA_def_property(srna, "interpolation_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, interpolation_method_items); + RNA_def_property_ui_text( + prop, "Interpolation", "Interpolation method to use for volumes in solid mode"); + RNA_def_property_update(prop, 0, "rna_Volume_update_display"); + + prop = RNA_def_property(srna, "axis_slice_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, axis_slice_method_items); + RNA_def_property_ui_text(prop, "Method", ""); + RNA_def_property_update(prop, 0, "rna_Volume_update_display"); + + prop = RNA_def_property(srna, "slice_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, axis_slice_position_items); + RNA_def_property_ui_text(prop, "Axis", ""); + + prop = RNA_def_property(srna, "slice_depth", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Position", "Position of the slice"); + RNA_def_property_update(prop, 0, "rna_Volume_update_display"); } static void rna_def_volume_render(BlenderRNA *brna) |