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
This commit is contained in:
Sriharsha Kotcharlakot 2020-09-15 21:21:14 +05:30
parent bedbd8655e
commit f137022f99
34 changed files with 1410 additions and 220 deletions

View File

@ -109,6 +109,8 @@ float *manta_get_phiobs_in(struct MANTA *fluid);
float *manta_get_phiobsstatic_in(struct MANTA *fluid);
float *manta_get_phiout_in(struct MANTA *fluid);
float *manta_get_phioutstatic_in(struct MANTA *fluid);
float *manta_get_phi(struct MANTA *fluid);
float *manta_get_pressure(struct MANTA *fluid);
/* Smoke functions */
void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd);

View File

@ -118,6 +118,7 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
mFuelIn = nullptr;
mReactIn = nullptr;
mEmissionIn = nullptr;
mPressure = nullptr;
/* Smoke high res grids. */
mDensityHigh = nullptr;
@ -2020,6 +2021,7 @@ void MANTA::updatePointers(FluidModifierData *fmd, bool flush)
mForceX = (smoke || liquid) ? getPointer<float>("x_force" + s_ext, func) : nullptr;
mForceY = (smoke || liquid) ? getPointer<float>("y_force" + s_ext, func) : nullptr;
mForceZ = (smoke || liquid) ? getPointer<float>("z_force" + s_ext, func) : nullptr;
mPressure = (smoke || liquid) ? getPointer<float>("pressure" + s_ext, func) : nullptr;
/* Outflow. */
mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr;

View File

@ -412,6 +412,10 @@ struct MANTA {
{
return mPhi;
}
inline float *getPressure()
{
return mPressure;
}
static atomic<int> solverID;
static int with_debug; /* On or off (1 or 0), also sets manta debug level. */
@ -806,6 +810,7 @@ struct MANTA {
int *mFlags;
float *mNumObstacle;
float *mNumGuide;
float *mPressure;
/* Smoke grids. */
float *mDensity;

View File

@ -362,6 +362,14 @@ float *manta_get_phioutstatic_in(MANTA *fluid)
{
return fluid->getPhiOutStaticIn();
}
float *manta_get_phi(MANTA *fluid)
{
return fluid->getPhi();
}
float *manta_get_pressure(MANTA *fluid)
{
return fluid->getPressure();
}
/* Smoke functions */
void manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd)

View File

@ -284,12 +284,13 @@ static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr,
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
lut3d->texture = GPU_texture_create_3d("OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, NULL);
lut3d->texture = GPU_texture_create_3d(
"OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
GPU_texture_filter_mode(lut3d->texture, true);
GPU_texture_wrap_mode(lut3d->texture, false, true);
lut3d->texture_display = GPU_texture_create_3d(
"OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, NULL);
"OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL);
GPU_texture_filter_mode(lut3d->texture_display, true);
GPU_texture_wrap_mode(lut3d->texture_display, false, true);

View File

@ -51,6 +51,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.sndparticle_bubble_buoyancy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-bubble-buoyancy"),
("bpy.types.fluiddomainsettings.sndparticle_combined_export*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-combined-export"),
("bpy.types.fluiddomainsettings.use_collision_border_bottom*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-bottom"),
("bpy.types.fluiddomainsettings.vector_scale_with_magnitude*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-scale-with-magnitude"),
("bpy.types.fluiddomainsettings.use_collision_border_front*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-front"),
("bpy.types.fluiddomainsettings.use_collision_border_right*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-right"),
("bpy.types.cyclesobjectsettings.use_adaptive_subdivision*", "render/cycles/object_settings/adaptive_subdiv.html#bpy-types-cyclesobjectsettings-use-adaptive-subdivision"),
@ -68,12 +69,18 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.sndparticle_bubble_drag*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-bubble-drag"),
("bpy.types.linestylegeometrymodifier_backbonestretcher*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/backbone_stretcher.html#bpy-types-linestylegeometrymodifier-backbonestretcher"),
("bpy.types.linestylegeometrymodifier_sinusdisplacement*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/sinus_displacement.html#bpy-types-linestylegeometrymodifier-sinusdisplacement"),
("bpy.types.fluiddomainsettings.color_ramp_field_scale*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-color-ramp-field-scale"),
("bpy.types.fluiddomainsettings.use_adaptive_timesteps*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-adaptive-timesteps"),
("bpy.types.fluiddomainsettings.use_dissolve_smoke_log*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-dissolve-smoke-log"),
("bpy.types.linestylegeometrymodifier_polygonalization*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/polygonization.html#bpy-types-linestylegeometrymodifier-polygonalization"),
("bpy.ops.view3d.edit_mesh_extrude_move_shrink_fatten*", "modeling/meshes/editing/face/extrude_faces_normal.html#bpy-ops-view3d-edit-mesh-extrude-move-shrink-fatten"),
("bpy.types.cyclesrendersettings.distance_cull_margin*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-distance-cull-margin"),
("bpy.types.fluiddomainsettings.display_interpolation*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-display-interpolation"),
("bpy.types.fluiddomainsettings.gridlines_cell_filter*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-gridlines-cell-filter"),
("bpy.types.fluiddomainsettings.gridlines_color_field*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-gridlines-color-field"),
("bpy.types.fluiddomainsettings.gridlines_lower_bound*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-gridlines-lower-bound"),
("bpy.types.fluiddomainsettings.gridlines_range_color*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-gridlines-range-color"),
("bpy.types.fluiddomainsettings.gridlines_upper_bound*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-gridlines-upper-bound"),
("bpy.types.materialgpencilstyle.use_fill_texture_mix*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-use-fill-texture-mix"),
("bpy.types.rendersettings_simplify_gpencil_shader_fx*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-shader-fx"),
("bpy.types.rendersettings_simplify_gpencil_view_fill*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-fill"),
@ -150,6 +157,7 @@ url_manual_mapping = (
("bpy.types.rigidbodyconstraint.solver_iterations*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-solver-iterations"),
("bpy.types.toolsettings.gpencil_stroke_placement*", "grease_pencil/modes/draw/stroke_placement.html#bpy-types-toolsettings-gpencil-stroke-placement"),
("bpy.types.cyclesrendersettings.use_camera_cull*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-use-camera-cull"),
("bpy.types.fluiddomainsettings.color_ramp_field*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-color-ramp-field"),
("bpy.types.fluiddomainsettings.guide_vel_factor*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-guide-vel-factor"),
("bpy.types.fluideffectorsettings.use_plane_init*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings-use-plane-init"),
("bpy.types.linestylegeometrymodifier_tipremover*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/tip_remover.html#bpy-types-linestylegeometrymodifier-tipremover"),
@ -191,6 +199,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.noise_strength*", "physics/fluid/type/domain/gas/noise.html#bpy-types-fluiddomainsettings-noise-strength"),
("bpy.types.fluiddomainsettings.particle_scale*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-particle-scale"),
("bpy.types.fluiddomainsettings.resolution_max*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-resolution-max"),
("bpy.types.fluiddomainsettings.show_gridlines*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-show-gridlines"),
("bpy.types.fluiddomainsettings.use_color_ramp*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-use-color-ramp"),
("bpy.types.fluiddomainsettings.viscosity_base*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-viscosity-base"),
("bpy.types.fluideffectorsettings.use_effector*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings-use-effector"),
@ -199,6 +208,7 @@ url_manual_mapping = (
("bpy.types.gpencilsculptguide.reference_point*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-reference-point"),
("bpy.types.linestylegeometrymodifier_2doffset*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/2d_offset.html#bpy-types-linestylegeometrymodifier-2doffset"),
("bpy.types.linestylegeometrymodifier_sampling*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/sampling.html#bpy-types-linestylegeometrymodifier-sampling"),
("bpy.types.volumedisplay.interpolation_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-interpolation-method"),
("bpy.types.clothsettings.use_pressure_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure-volume"),
("bpy.types.clothsettings.vertex_group_intern*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-intern"),
("bpy.types.cyclesrendersettings.*dicing_rate*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-rate"),
@ -225,7 +235,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.guide_source*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-guide-source"),
("bpy.types.fluiddomainsettings.particle_max*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-particle-max"),
("bpy.types.fluiddomainsettings.particle_min*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-particle-min"),
("bpy.types.fluiddomainsettings.slice_method*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-method"),
("bpy.types.fluiddomainsettings.vector_field*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-field"),
("bpy.types.fluiddomainsettings.vector_scale*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-scale"),
("bpy.types.fluideffectorsettings.guide_mode*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings-guide-mode"),
("bpy.types.fluidflowsettings.texture_offset*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-texture-offset"),
@ -268,6 +278,7 @@ url_manual_mapping = (
("bpy.types.sequenceeditor.use_overlay_lock*", "video_editing/preview/properties.html#bpy-types-sequenceeditor-use-overlay-lock"),
("bpy.types.spaceuveditor.show_pixel_coords*", "editors/uv/display_panel.html#bpy-types-spaceuveditor-show-pixel-coords"),
("bpy.types.toolsettings.gpencil_selectmode*", "grease_pencil/selecting.html#bpy-types-toolsettings-gpencil-selectmode"),
("bpy.types.volumedisplay.axis_slice_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-axis-slice-method"),
("bpy.ops.gpencil.active_frames_delete_all*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-active-frames-delete-all"),
("bpy.ops.gpencil.stroke_merge_by_distance*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-merge-by-distance"),
("bpy.ops.object.anim_transforms_to_deltas*", "scene_layout/object/editing/apply.html#bpy-ops-object-anim-transforms-to-deltas"),
@ -278,7 +289,6 @@ url_manual_mapping = (
("bpy.types.compositornodeplanetrackdeform*", "compositing/types/distort/plane_track_deform.html#bpy-types-compositornodeplanetrackdeform"),
("bpy.types.curve.bevel_factor_mapping_end*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-factor-mapping-end"),
("bpy.types.fluiddomainsettings.cache_type*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache-type"),
("bpy.types.fluiddomainsettings.coba_field*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-coba-field"),
("bpy.types.fluiddomainsettings.flip_ratio*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flip-ratio"),
("bpy.types.fluiddomainsettings.guide_beta*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-guide-beta"),
("bpy.types.fluiddomainsettings.mesh_scale*", "physics/fluid/type/domain/liquid/mesh.html#bpy-types-fluiddomainsettings-mesh-scale"),
@ -457,6 +467,7 @@ url_manual_mapping = (
("bpy.types.spacetexteditor.tab_width*", "editors/text_editor.html#bpy-types-spacetexteditor-tab-width"),
("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"),
("bpy.ops.mesh.customdata_mask_clear*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-mesh-customdata-mask-clear"),
("bpy.ops.mesh.extrude_vertices_move*", "modeling/meshes/editing/vertex/extrude_vertices.html#bpy-ops-mesh-extrude-vertices-move"),
("bpy.ops.mesh.mod_weighted_strength*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-mod-weighted-strength"),

View File

@ -523,6 +523,17 @@ class QuickLiquid(Operator):
# change domain type, will also allocate and show particle system for FLIP
obj.modifiers[-1].domain_settings.domain_type = 'LIQUID'
liquid_domain = obj.modifiers[-2]
# set color mapping field to show phi grid for liquid
liquid_domain.domain_settings.color_ramp_field = 'PHI'
# set slicing method to single
liquid_domain.domain_settings.axis_slice_method = 'SINGLE'
# set display thickness to a lower value for more detailed display of phi grids
liquid_domain.domain_settings.display_thickness = 0.02
# make the domain smooth so it renders nicely
bpy.ops.object.shade_smooth()

View File

@ -142,6 +142,9 @@ class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
volume = context.volume
display = volume.display
axis_slice_method = display.axis_slice_method
do_full_slicing = (axis_slice_method == 'FULL')
col = layout.column(align=True)
col.prop(display, "wireframe_type")
@ -149,7 +152,14 @@ class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
sub.active = display.wireframe_type in {'BOXES', 'POINTS'}
sub.prop(display, "wireframe_detail", text="Detail")
layout.prop(display, "density")
col = layout.column(align=True)
col.prop(display, "density")
col.prop(display, "interpolation_method")
col.prop(display, "axis_slice_method")
if not do_full_slicing:
col.prop(display, "slice_axis")
col.prop(display, "slice_depth")
class DATA_PT_custom_props_volume(DataButtonsPanel, PropertyPanel, Panel):

View File

@ -1290,7 +1290,7 @@ class PHYSICS_PT_viewport_display(PhysicButtonsPanel, Panel):
@classmethod
def poll(cls, context):
return (PhysicButtonsPanel.poll_gas_domain(context))
return (PhysicButtonsPanel.poll_fluid_domain(context))
def draw(self, context):
layout = self.layout
@ -1298,41 +1298,40 @@ class PHYSICS_PT_viewport_display(PhysicButtonsPanel, Panel):
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
domain = context.fluid.domain_settings
slice_method = domain.slice_method
axis_slice_method = domain.axis_slice_method
do_axis_slicing = (slice_method == 'AXIS_ALIGNED')
do_full_slicing = (axis_slice_method == 'FULL')
col = flow.column(align=False)
col.prop(domain, "display_thickness")
col.prop(domain, "display_interpolation")
col.separator()
col = flow.column()
col.prop(domain, "slice_method", text="Slicing")
sub = col.column()
sub.prop(domain, "display_interpolation")
if domain.use_color_ramp and domain.color_ramp_field == 'FLAGS':
sub.enabled = False
col = col.column()
col.active = do_axis_slicing
col.prop(domain, "axis_slice_method")
if not do_full_slicing and do_axis_slicing:
if not do_full_slicing:
col.prop(domain, "slice_axis")
col.prop(domain, "slice_depth")
if domain.display_interpolation == 'CLOSEST' or domain.color_ramp_field == 'FLAGS':
col.prop(domain, "show_gridlines")
col = col.column()
col.active = do_full_slicing or not do_axis_slicing
col.active = do_full_slicing
col.prop(domain, "slice_per_voxel")
class PHYSICS_PT_viewport_display_color(PhysicButtonsPanel, Panel):
bl_label = "Color Mapping"
bl_label = "Grid Display"
bl_parent_id = 'PHYSICS_PT_viewport_display'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return (PhysicButtonsPanel.poll_gas_domain(context))
return (PhysicButtonsPanel.poll_fluid_domain(context))
def draw_header(self, context):
md = context.fluid.domain_settings
@ -1346,22 +1345,26 @@ class PHYSICS_PT_viewport_display_color(PhysicButtonsPanel, Panel):
domain = context.fluid.domain_settings
col = layout.column()
col.active = domain.use_color_ramp
col.prop(domain, "coba_field")
col.prop(domain, "color_ramp_field")
if not domain.color_ramp_field == 'FLAGS':
col.prop(domain, "color_ramp_field_scale")
col.use_property_split = False
col = col.column()
col.template_color_ramp(domain, "color_ramp", expand=True)
if domain.color_ramp_field[:3] != 'PHI' and domain.color_ramp_field not in {'FLAGS', 'PRESSURE'}:
col = col.column()
col.template_color_ramp(domain, "color_ramp", expand=True)
class PHYSICS_PT_viewport_display_debug(PhysicButtonsPanel, Panel):
bl_label = "Debug Velocity"
bl_label = "Vector Display"
bl_parent_id = 'PHYSICS_PT_viewport_display'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return (PhysicButtonsPanel.poll_gas_domain(context))
return (PhysicButtonsPanel.poll_fluid_domain(context))
def draw_header(self, context):
md = context.fluid.domain_settings
@ -1378,8 +1381,52 @@ class PHYSICS_PT_viewport_display_debug(PhysicButtonsPanel, Panel):
col = flow.column()
col.active = domain.show_velocity
col.prop(domain, "vector_display_type", text="Display As")
if not domain.use_guide and domain.vector_field == 'GUIDE_VELOCITY':
note = layout.split()
note.label(icon='INFO', text="Enable Guides first! Defaulting to Fluid Velocity.")
if domain.vector_display_type == 'MAC':
sub = col.column(heading="MAC Grid")
sub.prop(domain, "vector_show_mac_x")
sub.prop(domain, "vector_show_mac_y")
sub.prop(domain, "vector_show_mac_z")
else:
col.prop(domain, "vector_scale_with_magnitude")
col.prop(domain, "vector_field")
col.prop(domain, "vector_scale")
class PHYSICS_PT_viewport_display_advanced(PhysicButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = 'PHYSICS_PT_viewport_display'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return PhysicButtonsPanel.poll_fluid_domain(context) and context.fluid.domain_settings.show_gridlines
def draw(self, context):
layout = self.layout
layout.use_property_split = True
domain = context.fluid.domain_settings
col = layout.column()
col.prop(domain, "gridlines_color_field", text="Color Gridlines")
if domain.gridlines_color_field == 'RANGE':
if domain.use_color_ramp and domain.color_ramp_field != 'FLAGS':
col.prop(domain, "gridlines_lower_bound")
col.prop(domain, "gridlines_upper_bound")
col.prop(domain, "gridlines_range_color")
col.prop(domain, "gridlines_cell_filter")
else:
note = layout.split()
if not domain.use_color_ramp:
note.label(icon='INFO', text="Enable Grid Display to use range highlighting!")
else:
note.label(icon='INFO', text="Range highlighting for flags is not available!")
classes = (
FLUID_PT_presets,
@ -1406,6 +1453,7 @@ classes = (
PHYSICS_PT_viewport_display,
PHYSICS_PT_viewport_display_color,
PHYSICS_PT_viewport_display_debug,
PHYSICS_PT_viewport_display_advanced,
)

View File

@ -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);

View File

@ -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)-- */

View File

@ -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)

View File

@ -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_call_procedural_lines(grp, ob, line_count);
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));
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
finalColor = vec4(weight_to_color(length(velocity)), 1.0);
#ifdef USE_MAC
vec3 color;
vector = (isCellCentered) ? get_vector_mac(cell_co) : get_vector(cell_co);
#ifdef USE_NEEDLE
mat3 rot_mat = rotation_from_vector(velocity);
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]];
pos += rotated_pos * length(velocity) * displaySize * cellSize;
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(color, 1.0);
#else
pos += ((gl_VertexID % 2) == 1) ? velocity * displaySize * cellSize : vec3(0.0);
vector = (isCellCentered) ? get_vector(cell_co) : get_vector_centered(cell_co);
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 * 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);

View File

@ -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

View File

@ -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. */
}
}
}
}

View File

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

View File

@ -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");

View File

@ -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);
if (use_slice) {
float invviewmat[4][4];
DRW_view_viewmat_get(NULL, invviewmat, true);
/* 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);
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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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(

View File

@ -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 ------ */

View File

@ -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;

View File

@ -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 \

View File

@ -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

View File

@ -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 */

View File

@ -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)