WIP: Brush assets project #106303
|
@ -723,6 +723,8 @@ struct GWL_SeatStatePointerScroll {
|
|||
int32_t discrete_xy[2] = {0, 0};
|
||||
/** Discrete scrolling, v8 of the seat API (handled & reset with pointer "frame" callback). */
|
||||
int32_t discrete120_xy[2] = {0, 0};
|
||||
/** Accumulated value from `discrete120_xy`, not reset between "frame" callbacks. */
|
||||
int32_t discrete120_xy_accum[2] = {0, 0};
|
||||
/** True when the axis is inverted (also known is "natural" scrolling). */
|
||||
bool inverted_xy[2] = {false, false};
|
||||
/** The source of scroll event. */
|
||||
|
@ -3813,12 +3815,13 @@ static void pointer_handle_frame(void *data, wl_pointer * /*wl_pointer*/)
|
|||
|
||||
/* Handle value120 to discrete steps first. */
|
||||
if (seat->pointer_scroll.discrete120_xy[0] || seat->pointer_scroll.discrete120_xy[1]) {
|
||||
/* The values will have been normalized so 120 represents a single click-step. */
|
||||
seat->pointer_scroll.discrete_xy[0] = seat->pointer_scroll.discrete120_xy[0] / 120;
|
||||
seat->pointer_scroll.discrete_xy[1] = seat->pointer_scroll.discrete120_xy[1] / 120;
|
||||
|
||||
seat->pointer_scroll.discrete120_xy[0] = 0;
|
||||
seat->pointer_scroll.discrete120_xy[1] = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
seat->pointer_scroll.discrete120_xy_accum[i] += seat->pointer_scroll.discrete120_xy[i];
|
||||
seat->pointer_scroll.discrete120_xy[i] = 0;
|
||||
/* The values will have been normalized so 120 represents a single click-step. */
|
||||
seat->pointer_scroll.discrete_xy[i] = seat->pointer_scroll.discrete120_xy_accum[i] / 120;
|
||||
seat->pointer_scroll.discrete120_xy_accum[i] -= seat->pointer_scroll.discrete_xy[i] * 120;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiple wheel events may have been generated and it's not known which.
|
||||
|
|
|
@ -4,7 +4,6 @@ options = eevee.ray_tracing_options
|
|||
|
||||
eevee.ray_tracing_method = 'SCREEN'
|
||||
options.resolution_scale = '2'
|
||||
options.sample_clamp = 10.0
|
||||
options.trace_max_roughness = 0.5
|
||||
options.screen_trace_quality = 0.25
|
||||
options.screen_trace_thickness = 0.20000000298023224
|
||||
|
|
|
@ -541,7 +541,6 @@ class AddPresetEEVEERaytracing(AddPresetBase, Operator):
|
|||
preset_values = [
|
||||
"eevee.ray_tracing_method",
|
||||
"options.resolution_scale",
|
||||
"options.sample_clamp",
|
||||
"options.trace_max_roughness",
|
||||
"options.screen_trace_quality",
|
||||
"options.screen_trace_thickness",
|
||||
|
|
|
@ -720,6 +720,7 @@ class NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeGridToMesh")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSDFGridBoolean")
|
||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Operations")
|
||||
|
||||
|
||||
|
|
|
@ -721,11 +721,9 @@ class RENDER_PT_eevee_next_clamping_surface(RenderButtonsPanel, Panel):
|
|||
scene = context.scene
|
||||
props = scene.eevee
|
||||
|
||||
# TODO(fclem): Add clamp properties
|
||||
options = props.ray_tracing_options
|
||||
layout.prop(options, "sample_clamp", text="Indirect Light")
|
||||
# layout.prop(props, "clamp_surface_direct", text="Direct Light")
|
||||
# layout.prop(props, "clamp_surface_indirect", text="Indirect Light")
|
||||
col = layout.column(align=True)
|
||||
col.prop(props, "clamp_surface_direct", text="Direct Light")
|
||||
col.prop(props, "clamp_surface_indirect", text="Indirect Light")
|
||||
|
||||
|
||||
class RENDER_PT_eevee_next_clamping_volume(RenderButtonsPanel, Panel):
|
||||
|
@ -743,9 +741,10 @@ class RENDER_PT_eevee_next_clamping_volume(RenderButtonsPanel, Panel):
|
|||
layout.use_property_decorate = False
|
||||
scene = context.scene
|
||||
props = scene.eevee
|
||||
layout.prop(props, "volumetric_light_clamp", text="Direct Light")
|
||||
# layout.prop(props, "clamp_volumetric_direct", text="Direct Light")
|
||||
# layout.prop(props, "clamp_volumetric_indirect", text="Indirect Light")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(props, "clamp_volume_direct", text="Direct Light")
|
||||
col.prop(props, "clamp_volume_indirect", text="Indirect Light")
|
||||
|
||||
|
||||
class RENDER_PT_eevee_next_sampling_shadows(RenderButtonsPanel, Panel):
|
||||
|
|
|
@ -2764,6 +2764,7 @@ class SEQUENCER_PT_snapping(Panel):
|
|||
col = layout.column(heading="Snap to", align=True)
|
||||
col.prop(sequencer_tool_settings, "snap_to_current_frame")
|
||||
col.prop(sequencer_tool_settings, "snap_to_hold_offset")
|
||||
col.prop(sequencer_tool_settings, "snap_to_markers")
|
||||
|
||||
col = layout.column(heading="Ignore", align=True)
|
||||
col.prop(sequencer_tool_settings, "snap_ignore_muted", text="Muted Strips")
|
||||
|
|
|
@ -2720,6 +2720,23 @@ class _defs_gpencil_weight:
|
|||
]
|
||||
|
||||
|
||||
class _defs_grease_pencil_weight:
|
||||
|
||||
@staticmethod
|
||||
def generate_from_brushes(context):
|
||||
return generate_from_enum_ex(
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="ops.gpencil.sculpt_",
|
||||
type=bpy.types.Brush,
|
||||
# Uses GPv2 tool settings
|
||||
attr="gpencil_weight_tool",
|
||||
# tooldef_keywords=dict(
|
||||
# operator="grease_pencil.weight_paint",
|
||||
# ),
|
||||
)
|
||||
|
||||
|
||||
class _defs_curves_sculpt:
|
||||
|
||||
@staticmethod
|
||||
|
@ -3533,6 +3550,11 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'WEIGHT_GREASE_PENCIL': [
|
||||
_defs_grease_pencil_weight.generate_from_brushes,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'VERTEX_GPENCIL': [
|
||||
_defs_gpencil_vertex.generate_from_brushes,
|
||||
None,
|
||||
|
|
|
@ -1188,12 +1188,11 @@ class VIEW3D_MT_editor_menus(Menu):
|
|||
elif mode_string == 'VERTEX_GPENCIL':
|
||||
layout.menu("VIEW3D_MT_select_edit_gpencil")
|
||||
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
||||
if obj.type == 'MESH':
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask")
|
||||
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask")
|
||||
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
|
||||
elif mode_string not in {'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL'}:
|
||||
layout.menu("VIEW3D_MT_select_%s" % mode_string.lower())
|
||||
|
||||
|
@ -3611,10 +3610,8 @@ class VIEW3D_MT_paint_weight(Menu):
|
|||
|
||||
layout.menu("VIEW3D_MT_paint_weight_lock", text="Locks")
|
||||
|
||||
def draw(self, context):
|
||||
obj = context.active_object
|
||||
if obj.type == 'MESH':
|
||||
self.draw_generic(self.layout, is_editmode=False)
|
||||
def draw(self, _context):
|
||||
self.draw_generic(self.layout, is_editmode=False)
|
||||
|
||||
|
||||
class VIEW3D_MT_sculpt(Menu):
|
||||
|
|
|
@ -37,6 +37,9 @@ enum class SingleKeyingResult {
|
|||
FCURVE_NOT_KEYFRAMEABLE,
|
||||
NO_KEY_NEEDED,
|
||||
UNABLE_TO_INSERT_TO_NLA_STACK,
|
||||
ID_NOT_EDITABLE,
|
||||
ID_NOT_ANIMATABLE,
|
||||
CANNOT_RESOLVE_PATH,
|
||||
/* Make sure to always keep this at the end of the enum. */
|
||||
_KEYING_RESULT_MAX,
|
||||
};
|
||||
|
@ -85,15 +88,14 @@ void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop);
|
|||
* \param array_index: The index to key or -1 keys all array indices.
|
||||
* \return The number of key-frames inserted.
|
||||
*/
|
||||
int insert_keyframe(Main *bmain,
|
||||
ReportList *reports,
|
||||
ID *id,
|
||||
const char group[],
|
||||
const char rna_path[],
|
||||
int array_index,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
eBezTriple_KeyframeType keytype,
|
||||
eInsertKeyFlags flag);
|
||||
CombinedKeyingResult insert_keyframe(Main *bmain,
|
||||
ID &id,
|
||||
const char group[],
|
||||
const char rna_path[],
|
||||
int array_index,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
eBezTriple_KeyframeType keytype,
|
||||
eInsertKeyFlags flag);
|
||||
|
||||
/**
|
||||
* \brief Secondary Insert Key-framing API call.
|
||||
|
|
|
@ -127,6 +127,40 @@ void CombinedKeyingResult::generate_reports(ReportList *reports)
|
|||
error_count > 1 ? "s have" : " has"));
|
||||
}
|
||||
|
||||
if (this->get_count(SingleKeyingResult::ID_NOT_EDITABLE) > 0) {
|
||||
const int error_count = this->get_count(SingleKeyingResult::ID_NOT_EDITABLE);
|
||||
if (error_count == 1) {
|
||||
errors.append("Inserting keys for one ID has been skipped because it is not editable.");
|
||||
}
|
||||
else {
|
||||
errors.append(
|
||||
fmt::format("{} IDs have been skipped because they are not editable.", error_count));
|
||||
}
|
||||
}
|
||||
|
||||
if (this->get_count(SingleKeyingResult::ID_NOT_ANIMATABLE) > 0) {
|
||||
const int error_count = this->get_count(SingleKeyingResult::ID_NOT_ANIMATABLE);
|
||||
if (error_count == 1) {
|
||||
errors.append("Inserting keys for one ID has been skipped because it cannot be animated.");
|
||||
}
|
||||
else {
|
||||
errors.append(
|
||||
fmt::format("{} IDs have been skipped because they cannot be animated.", error_count));
|
||||
}
|
||||
}
|
||||
|
||||
if (this->get_count(SingleKeyingResult::CANNOT_RESOLVE_PATH) > 0) {
|
||||
const int error_count = this->get_count(SingleKeyingResult::CANNOT_RESOLVE_PATH);
|
||||
if (error_count == 1) {
|
||||
errors.append(
|
||||
"Inserting keys for one ID has been skipped because the RNA path wasn't valid for it");
|
||||
}
|
||||
else {
|
||||
errors.append(fmt::format(
|
||||
"{} IDs have been skipped because the RNA path wasn't valid for them.", error_count));
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.is_empty()) {
|
||||
BKE_report(reports, RPT_WARNING, "Encountered unhandled error during keyframing");
|
||||
return;
|
||||
|
@ -556,54 +590,40 @@ static SingleKeyingResult insert_keyframe_fcurve_value(Main *bmain,
|
|||
return result;
|
||||
}
|
||||
|
||||
int insert_keyframe(Main *bmain,
|
||||
ReportList *reports,
|
||||
ID *id,
|
||||
const char group[],
|
||||
const char rna_path[],
|
||||
int array_index,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
eBezTriple_KeyframeType keytype,
|
||||
eInsertKeyFlags flag)
|
||||
CombinedKeyingResult insert_keyframe(Main *bmain,
|
||||
ID &id,
|
||||
const char group[],
|
||||
const char rna_path[],
|
||||
int array_index,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
eBezTriple_KeyframeType keytype,
|
||||
eInsertKeyFlags flag)
|
||||
{
|
||||
if (id == nullptr) {
|
||||
BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path);
|
||||
return 0;
|
||||
}
|
||||
CombinedKeyingResult combined_result;
|
||||
|
||||
if (!BKE_id_is_editable(bmain, id)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "'%s' on %s is not editable", rna_path, id->name + 2);
|
||||
return 0;
|
||||
if (!BKE_id_is_editable(bmain, &id)) {
|
||||
combined_result.add(SingleKeyingResult::ID_NOT_EDITABLE);
|
||||
return combined_result;
|
||||
}
|
||||
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop = nullptr;
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(id);
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(&id);
|
||||
if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
|
||||
BKE_reportf(
|
||||
reports,
|
||||
RPT_ERROR,
|
||||
"Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)",
|
||||
(id) ? id->name : RPT_("<Missing ID block>"),
|
||||
rna_path);
|
||||
return 0;
|
||||
combined_result.add(SingleKeyingResult::CANNOT_RESOLVE_PATH);
|
||||
return combined_result;
|
||||
}
|
||||
|
||||
bAction *act = id_action_ensure(bmain, id);
|
||||
bAction *act = id_action_ensure(bmain, &id);
|
||||
if (act == nullptr) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Could not insert keyframe, as this type does not support animation data (ID = "
|
||||
"%s, path = %s)",
|
||||
id->name,
|
||||
rna_path);
|
||||
return 0;
|
||||
combined_result.add(SingleKeyingResult::ID_NOT_ANIMATABLE);
|
||||
return combined_result;
|
||||
}
|
||||
|
||||
/* Apply NLA-mapping to frame to use (if applicable). */
|
||||
NlaKeyframingContext *nla_context = nullptr;
|
||||
ListBase nla_cache = {nullptr, nullptr};
|
||||
AnimData *adt = BKE_animdata_from_id(id);
|
||||
AnimData *adt = BKE_animdata_from_id(&id);
|
||||
const float nla_mapped_frame = nla_time_remap(
|
||||
anim_eval_context, &id_ptr, adt, act, &nla_cache, &nla_context);
|
||||
|
||||
|
@ -611,17 +631,15 @@ int insert_keyframe(Main *bmain,
|
|||
Vector<float> values = get_keyframe_values(&ptr, prop, visual_keyframing);
|
||||
|
||||
bool force_all;
|
||||
BitVector<> successful_remaps = nla_map_keyframe_values_and_generate_reports(
|
||||
values.as_mutable_span(),
|
||||
array_index,
|
||||
ptr,
|
||||
*prop,
|
||||
nla_context,
|
||||
anim_eval_context,
|
||||
reports,
|
||||
&force_all);
|
||||
|
||||
CombinedKeyingResult combined_result;
|
||||
BitVector<> successful_remaps(values.size(), false);
|
||||
BKE_animsys_nla_remap_keyframe_values(nla_context,
|
||||
&ptr,
|
||||
prop,
|
||||
values,
|
||||
array_index,
|
||||
anim_eval_context,
|
||||
&force_all,
|
||||
successful_remaps);
|
||||
|
||||
/* Key the entire array. */
|
||||
int key_count = 0;
|
||||
|
@ -738,11 +756,7 @@ int insert_keyframe(Main *bmain,
|
|||
}
|
||||
}
|
||||
|
||||
if (key_count == 0) {
|
||||
combined_result.generate_reports(reports);
|
||||
}
|
||||
|
||||
return key_count;
|
||||
return combined_result;
|
||||
}
|
||||
|
||||
/* ************************************************** */
|
||||
|
|
|
@ -99,6 +99,10 @@ bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
|
|||
|
||||
void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span<std::string> rna_paths)
|
||||
{
|
||||
BLI_assert(ob != nullptr);
|
||||
BLI_assert(scene != nullptr);
|
||||
BLI_assert(C != nullptr);
|
||||
|
||||
ID *id = &ob->id;
|
||||
if (!autokeyframe_cfra_can_key(scene, id)) {
|
||||
return;
|
||||
|
@ -134,16 +138,20 @@ void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span<std::string
|
|||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
if (adt && adt->action) {
|
||||
CombinedKeyingResult combined_result;
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) {
|
||||
insert_keyframe(bmain,
|
||||
reports,
|
||||
id,
|
||||
(fcu->grp ? fcu->grp->name : nullptr),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
CombinedKeyingResult result = insert_keyframe(bmain,
|
||||
*id,
|
||||
(fcu->grp ? fcu->grp->name : nullptr),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
combined_result.merge(result);
|
||||
}
|
||||
if (combined_result.get_count(SingleKeyingResult::SUCCESS) == 0) {
|
||||
combined_result.generate_reports(reports);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -206,6 +214,11 @@ void autokeyframe_pose_channel(bContext *C,
|
|||
Span<std::string> rna_paths,
|
||||
short targetless_ik)
|
||||
{
|
||||
BLI_assert(C != nullptr);
|
||||
BLI_assert(scene != nullptr);
|
||||
BLI_assert(ob != nullptr);
|
||||
BLI_assert(pose_channel != nullptr);
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ID *id = &ob->id;
|
||||
AnimData *adt = ob->adt;
|
||||
|
@ -234,12 +247,12 @@ void autokeyframe_pose_channel(bContext *C,
|
|||
flag |= INSERTKEY_MATRIX;
|
||||
}
|
||||
|
||||
blender::Vector<PointerRNA> sources;
|
||||
Vector<PointerRNA> sources;
|
||||
/* Add data-source override for the camera object. */
|
||||
ANIM_relative_keyingset_add_source(sources, id, &RNA_PoseBone, pose_channel);
|
||||
|
||||
/* only insert into active keyingset? */
|
||||
if (blender::animrig::is_keying_flag(scene, AUTOKEY_FLAG_ONLYKEYINGSET) && (active_ks)) {
|
||||
if (is_keying_flag(scene, AUTOKEY_FLAG_ONLYKEYINGSET) && (active_ks)) {
|
||||
/* Run the active Keying Set on the current data-source. */
|
||||
ANIM_apply_keyingset(
|
||||
C, &sources, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
|
||||
|
@ -247,7 +260,7 @@ void autokeyframe_pose_channel(bContext *C,
|
|||
}
|
||||
|
||||
/* only insert into available channels? */
|
||||
if (blender::animrig::is_keying_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
if (is_keying_flag(scene, AUTOKEY_FLAG_INSERTAVAILABLE)) {
|
||||
if (!act) {
|
||||
return;
|
||||
}
|
||||
|
@ -262,15 +275,17 @@ void autokeyframe_pose_channel(bContext *C,
|
|||
* NOTE: this will do constraints too, but those are ok to do here too?
|
||||
*/
|
||||
if (STREQ(pchan_name, pose_channel->name)) {
|
||||
blender::animrig::insert_keyframe(bmain,
|
||||
reports,
|
||||
id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
CombinedKeyingResult result = insert_keyframe(bmain,
|
||||
*id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
if (result.get_count(SingleKeyingResult::SUCCESS) == 0) {
|
||||
result.generate_reports(reports);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -302,7 +317,6 @@ bool autokeyframe_property(bContext *C,
|
|||
bAction *action;
|
||||
bool driven;
|
||||
bool special;
|
||||
bool changed = false;
|
||||
|
||||
/* For entire array buttons we check the first component, it's not perfect
|
||||
* but works well enough in typical cases. */
|
||||
|
@ -313,13 +327,14 @@ bool autokeyframe_property(bContext *C,
|
|||
/* Only early out when we actually want an existing F-curve already
|
||||
* (e.g. auto-keyframing from buttons). */
|
||||
if (fcu == nullptr && (driven || special || only_if_property_keyed)) {
|
||||
return changed;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (driven) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
if (special) {
|
||||
/* NLA Strip property. */
|
||||
if (is_autokey_on(scene)) {
|
||||
|
@ -343,7 +358,6 @@ bool autokeyframe_property(bContext *C,
|
|||
|
||||
/* TODO: this should probably respect the keyingset only option for anim */
|
||||
if (autokeyframe_cfra_can_key(scene, id)) {
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
const eInsertKeyFlags flag = get_autokey_flags(scene);
|
||||
const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
|
||||
|
@ -354,16 +368,16 @@ bool autokeyframe_property(bContext *C,
|
|||
* E.g., color wheels (see #42567). */
|
||||
BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1));
|
||||
}
|
||||
changed = insert_keyframe(bmain,
|
||||
reports,
|
||||
id,
|
||||
(fcu && fcu->grp) ? fcu->grp->name : nullptr,
|
||||
fcu ? fcu->rna_path : (path ? path->c_str() : nullptr),
|
||||
rnaindex,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag) != 0;
|
||||
|
||||
CombinedKeyingResult result = insert_keyframe(bmain,
|
||||
*id,
|
||||
(fcu && fcu->grp) ? fcu->grp->name : nullptr,
|
||||
fcu ? fcu->rna_path :
|
||||
(path ? path->c_str() : nullptr),
|
||||
rnaindex,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
changed = result.get_count(SingleKeyingResult::SUCCESS) != 0;
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,8 +142,9 @@ enum eContextObjectMode {
|
|||
CTX_MODE_SCULPT_CURVES,
|
||||
CTX_MODE_PAINT_GREASE_PENCIL,
|
||||
CTX_MODE_SCULPT_GREASE_PENCIL,
|
||||
CTX_MODE_WEIGHT_GREASE_PENCIL,
|
||||
};
|
||||
#define CTX_MODE_NUM (CTX_MODE_SCULPT_GREASE_PENCIL + 1)
|
||||
#define CTX_MODE_NUM (CTX_MODE_WEIGHT_GREASE_PENCIL + 1)
|
||||
|
||||
/* Context */
|
||||
|
||||
|
|
|
@ -1277,6 +1277,7 @@ void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index
|
|||
#define GEO_NODE_POINTS_TO_SDF_GRID 2128
|
||||
#define GEO_NODE_GRID_TO_MESH 2129
|
||||
#define GEO_NODE_DISTRIBUTE_POINTS_IN_GRID 2130
|
||||
#define GEO_NODE_SDF_GRID_BOOLEAN 2131
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ set(INC
|
|||
../makesrna
|
||||
../modifiers
|
||||
../nodes
|
||||
../nodes/geometry/include
|
||||
../render
|
||||
../sequencer
|
||||
../shader_fx
|
||||
|
|
|
@ -1197,7 +1197,12 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
|
|||
}
|
||||
}
|
||||
if (object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
return CTX_MODE_WEIGHT_GREASE_PENCIL;
|
||||
}
|
||||
}
|
||||
if (object_mode & OB_MODE_VERTEX_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_VERTEX_GPENCIL_LEGACY;
|
||||
|
@ -1252,6 +1257,7 @@ static const char *data_mode_strings[] = {
|
|||
"curves_sculpt",
|
||||
"grease_pencil_paint",
|
||||
"grease_pencil_sculpt",
|
||||
"grease_pencil_weight",
|
||||
nullptr,
|
||||
};
|
||||
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1,
|
||||
|
|
|
@ -2934,9 +2934,6 @@ static void read_drawing_array(GreasePencil &grease_pencil, BlendDataReader *rea
|
|||
break;
|
||||
}
|
||||
case GP_DRAWING_REFERENCE: {
|
||||
GreasePencilDrawingReference *drawing_reference =
|
||||
reinterpret_cast<GreasePencilDrawingReference *>(drawing_base);
|
||||
BLO_read_data_address(reader, &drawing_reference->id_reference);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,10 @@
|
|||
|
||||
#include "NOD_common.h"
|
||||
#include "NOD_composite.hh"
|
||||
#include "NOD_geo_bake.hh"
|
||||
#include "NOD_geo_index_switch.hh"
|
||||
#include "NOD_geo_repeat.hh"
|
||||
#include "NOD_geo_simulation.hh"
|
||||
#include "NOD_geometry.hh"
|
||||
#include "NOD_geometry_nodes_lazy_function.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
|
@ -90,7 +94,6 @@
|
|||
#include "NOD_shader.h"
|
||||
#include "NOD_socket.hh"
|
||||
#include "NOD_texture.h"
|
||||
#include "NOD_zone_socket_items.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_build.hh"
|
||||
|
|
|
@ -606,6 +606,7 @@ PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref)
|
|||
return PaintMode::VertexGPencil;
|
||||
case CTX_MODE_SCULPT_GPENCIL_LEGACY:
|
||||
return PaintMode::SculptGPencil;
|
||||
case CTX_MODE_WEIGHT_GREASE_PENCIL:
|
||||
case CTX_MODE_WEIGHT_GPENCIL_LEGACY:
|
||||
return PaintMode::WeightGPencil;
|
||||
case CTX_MODE_SCULPT_CURVES:
|
||||
|
|
|
@ -499,20 +499,20 @@ int BLI_gset_buckets_len(const GSet *gs);
|
|||
*
|
||||
* Smaller is better!
|
||||
*/
|
||||
double BLI_ghash_calc_quality_ex(GHash *gh,
|
||||
double BLI_ghash_calc_quality_ex(const GHash *gh,
|
||||
double *r_load,
|
||||
double *r_variance,
|
||||
double *r_prop_empty_buckets,
|
||||
double *r_prop_overloaded_buckets,
|
||||
int *r_biggest_bucket);
|
||||
double BLI_gset_calc_quality_ex(GSet *gs,
|
||||
double BLI_gset_calc_quality_ex(const GSet *gs,
|
||||
double *r_load,
|
||||
double *r_variance,
|
||||
double *r_prop_empty_buckets,
|
||||
double *r_prop_overloaded_buckets,
|
||||
int *r_biggest_bucket);
|
||||
double BLI_ghash_calc_quality(GHash *gh);
|
||||
double BLI_gset_calc_quality(GSet *gs);
|
||||
double BLI_ghash_calc_quality(const GHash *gh);
|
||||
double BLI_gset_calc_quality(const GSet *gs);
|
||||
#endif /* GHASH_INTERNAL_API */
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -36,7 +36,7 @@ typedef struct LinkNodePair {
|
|||
} LinkNodePair;
|
||||
|
||||
int BLI_linklist_count(const LinkNode *list) ATTR_WARN_UNUSED_RESULT;
|
||||
int BLI_linklist_index(const LinkNode *list, void *ptr) ATTR_WARN_UNUSED_RESULT;
|
||||
int BLI_linklist_index(const LinkNode *list, const void *ptr) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
LinkNode *BLI_linklist_find(LinkNode *list, int index) ATTR_WARN_UNUSED_RESULT;
|
||||
LinkNode *BLI_linklist_find_last(LinkNode *list) ATTR_WARN_UNUSED_RESULT;
|
||||
|
|
|
@ -1089,7 +1089,7 @@ int BLI_gset_buckets_len(const GSet *gs)
|
|||
return BLI_ghash_buckets_len((const GHash *)gs);
|
||||
}
|
||||
|
||||
double BLI_ghash_calc_quality_ex(GHash *gh,
|
||||
double BLI_ghash_calc_quality_ex(const GHash *gh,
|
||||
double *r_load,
|
||||
double *r_variance,
|
||||
double *r_prop_empty_buckets,
|
||||
|
@ -1176,14 +1176,14 @@ double BLI_ghash_calc_quality_ex(GHash *gh,
|
|||
((double)gh->nentries * (gh->nentries + 2 * gh->nbuckets - 1)));
|
||||
}
|
||||
}
|
||||
double BLI_gset_calc_quality_ex(GSet *gs,
|
||||
double BLI_gset_calc_quality_ex(const GSet *gs,
|
||||
double *r_load,
|
||||
double *r_variance,
|
||||
double *r_prop_empty_buckets,
|
||||
double *r_prop_overloaded_buckets,
|
||||
int *r_biggest_bucket)
|
||||
{
|
||||
return BLI_ghash_calc_quality_ex((GHash *)gs,
|
||||
return BLI_ghash_calc_quality_ex((const GHash *)gs,
|
||||
r_load,
|
||||
r_variance,
|
||||
r_prop_empty_buckets,
|
||||
|
@ -1191,11 +1191,11 @@ double BLI_gset_calc_quality_ex(GSet *gs,
|
|||
r_biggest_bucket);
|
||||
}
|
||||
|
||||
double BLI_ghash_calc_quality(GHash *gh)
|
||||
double BLI_ghash_calc_quality(const GHash *gh)
|
||||
{
|
||||
return BLI_ghash_calc_quality_ex(gh, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
double BLI_gset_calc_quality(GSet *gs)
|
||||
double BLI_gset_calc_quality(const GSet *gs)
|
||||
{
|
||||
return BLI_ghash_calc_quality_ex((GHash *)gs, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ int BLI_linklist_count(const LinkNode *list)
|
|||
return len;
|
||||
}
|
||||
|
||||
int BLI_linklist_index(const LinkNode *list, void *ptr)
|
||||
int BLI_linklist_index(const LinkNode *list, const void *ptr)
|
||||
{
|
||||
int index;
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ BLI_INLINE uint mempool_maxchunks(const uint elem_num, const uint pchunk)
|
|||
return (elem_num <= pchunk) ? 1 : ((elem_num / pchunk) + 1);
|
||||
}
|
||||
|
||||
static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool)
|
||||
static BLI_mempool_chunk *mempool_chunk_alloc(const BLI_mempool *pool)
|
||||
{
|
||||
return MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "mempool chunk");
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "BKE_tracking.h"
|
||||
|
||||
#include "SEQ_iterator.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
|
||||
#include "ANIM_armature_iter.hh"
|
||||
#include "ANIM_bone_collections.hh"
|
||||
|
@ -2859,7 +2860,6 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
scene->eevee.ray_tracing_options.screen_trace_quality = 0.25f;
|
||||
scene->eevee.ray_tracing_options.screen_trace_thickness = 0.2f;
|
||||
scene->eevee.ray_tracing_options.trace_max_roughness = 0.5f;
|
||||
scene->eevee.ray_tracing_options.sample_clamp = 10.0f;
|
||||
scene->eevee.ray_tracing_options.resolution_scale = 2;
|
||||
}
|
||||
}
|
||||
|
@ -3216,6 +3216,17 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
/* Keep legacy EEVEE old behavior. */
|
||||
scene->eevee.flag |= SCE_EEVEE_VOLUME_CUSTOM_RANGE;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
scene->eevee.clamp_surface_indirect = 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 20)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
|
||||
sequencer_tool_settings->snap_mode |= SEQ_SNAP_TO_MARKERS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 20)) {
|
||||
|
|
|
@ -125,8 +125,8 @@ MemoryBuffer *MemoryBuffer::inflate() const
|
|||
float MemoryBuffer::get_max_value() const
|
||||
{
|
||||
float result = buffer_[0];
|
||||
const uint size = this->buffer_len();
|
||||
uint i;
|
||||
const int64_t size = this->buffer_len();
|
||||
int64_t i;
|
||||
|
||||
const float *fp_src = buffer_;
|
||||
|
||||
|
@ -408,7 +408,7 @@ void MemoryBuffer::fill_from(const MemoryBuffer &src)
|
|||
void MemoryBuffer::write_pixel(int x, int y, const float color[4])
|
||||
{
|
||||
if (x >= rect_.xmin && x < rect_.xmax && y >= rect_.ymin && y < rect_.ymax) {
|
||||
const int offset = get_coords_offset(x, y);
|
||||
const intptr_t offset = get_coords_offset(x, y);
|
||||
memcpy(&buffer_[offset], color, sizeof(float) * num_channels_);
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ void MemoryBuffer::write_pixel(int x, int y, const float color[4])
|
|||
void MemoryBuffer::add_pixel(int x, int y, const float color[4])
|
||||
{
|
||||
if (x >= rect_.xmin && x < rect_.xmax && y >= rect_.ymin && y < rect_.ymax) {
|
||||
const int offset = get_coords_offset(x, y);
|
||||
const intptr_t offset = get_coords_offset(x, y);
|
||||
float *dst = &buffer_[offset];
|
||||
const float *src = color;
|
||||
for (int i = 0; i < num_channels_; i++, dst++, src++) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
struct ColormanageProcessor;
|
||||
|
@ -285,6 +286,12 @@ class MemoryBuffer {
|
|||
get_relative_y(y));
|
||||
}
|
||||
|
||||
void read_elem_bicubic_bspline(float x, float y, float *out) const
|
||||
{
|
||||
math::interpolate_cubic_bspline_fl(
|
||||
buffer_, out, this->get_width(), this->get_height(), num_channels_, x, y);
|
||||
}
|
||||
|
||||
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
|
||||
{
|
||||
switch (sampler) {
|
||||
|
@ -292,10 +299,12 @@ class MemoryBuffer {
|
|||
read_elem_checked(x, y, out);
|
||||
break;
|
||||
case PixelSampler::Bilinear:
|
||||
case PixelSampler::Bicubic:
|
||||
/* No bicubic. Current implementation produces fuzzy results. */
|
||||
read_elem_bilinear(x, y, out);
|
||||
break;
|
||||
case PixelSampler::Bicubic:
|
||||
/* Using same method as GPU compositor. Final results may still vary. */
|
||||
read_elem_bicubic_bspline(x, y, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,9 +658,9 @@ class MemoryBuffer {
|
|||
|
||||
private:
|
||||
void set_strides();
|
||||
const int buffer_len() const
|
||||
const int64_t buffer_len() const
|
||||
{
|
||||
return get_memory_width() * get_memory_height();
|
||||
return int64_t(get_memory_width()) * int64_t(get_memory_height());
|
||||
}
|
||||
|
||||
void clear_elem(float *out) const
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
|
@ -302,6 +303,38 @@ DEGObjectIterData &DEGObjectIterData::operator=(const DEGObjectIterData &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
static Object *find_object_with_preview_geometry(const ViewerPath &viewer_path)
|
||||
{
|
||||
if (BLI_listbase_is_empty(&viewer_path.path)) {
|
||||
return nullptr;
|
||||
}
|
||||
const ViewerPathElem *elem = static_cast<const ViewerPathElem *>(viewer_path.path.first);
|
||||
if (elem->type != VIEWER_PATH_ELEM_TYPE_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
const IDViewerPathElem *id_elem = reinterpret_cast<const IDViewerPathElem *>(elem);
|
||||
if (id_elem->id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GS(id_elem->id->name) != ID_OB) {
|
||||
return nullptr;
|
||||
}
|
||||
Object *object = reinterpret_cast<Object *>(id_elem->id);
|
||||
if (elem->next->type != VIEWER_PATH_ELEM_TYPE_MODIFIER) {
|
||||
return nullptr;
|
||||
}
|
||||
const ModifierViewerPathElem *modifier_elem = reinterpret_cast<const ModifierViewerPathElem *>(
|
||||
elem->next);
|
||||
ModifierData *md = BKE_modifiers_findby_name(object, modifier_elem->modifier_name);
|
||||
if (md == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!(md->mode & eModifierMode_Realtime)) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<Object *>(id_elem->id);
|
||||
}
|
||||
|
||||
void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
|
||||
{
|
||||
Depsgraph *depsgraph = data->graph;
|
||||
|
@ -329,17 +362,7 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
|
|||
/* Determine if the preview of any object should be in the iterator. */
|
||||
const ViewerPath *viewer_path = data->settings->viewer_path;
|
||||
if (viewer_path != nullptr) {
|
||||
if (!BLI_listbase_is_empty(&viewer_path->path)) {
|
||||
const ViewerPathElem *elem = static_cast<const ViewerPathElem *>(viewer_path->path.first);
|
||||
if (elem->type == VIEWER_PATH_ELEM_TYPE_ID) {
|
||||
const IDViewerPathElem *id_elem = reinterpret_cast<const IDViewerPathElem *>(elem);
|
||||
if (id_elem->id != nullptr) {
|
||||
if (GS(id_elem->id->name) == ID_OB) {
|
||||
data->object_orig_with_preview = reinterpret_cast<Object *>(id_elem->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data->object_orig_with_preview = find_object_with_preview_geometry(*viewer_path);
|
||||
}
|
||||
|
||||
DEG_iterator_objects_next(iter);
|
||||
|
|
|
@ -681,11 +681,11 @@ enum EEVEE_EffectsFlag {
|
|||
EFFECT_TAA = (1 << 8),
|
||||
EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
|
||||
EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
|
||||
EFFECT_RADIANCE_BUFFER = (1 << 10), /* Not really an effect but a feature */
|
||||
EFFECT_SSS = (1 << 11),
|
||||
EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */
|
||||
EFFECT_TAA_REPROJECT = (1 << 13), /* should be mutually exclusive with EFFECT_TAA */
|
||||
EFFECT_DEPTH_DOUBLE_BUFFER = (1 << 14), /* Not really an effect but a feature */
|
||||
EFFECT_RADIANCE_BUFFER = (1 << 11), /* Not really an effect but a feature */
|
||||
EFFECT_SSS = (1 << 12),
|
||||
EFFECT_VELOCITY_BUFFER = (1 << 13), /* Not really an effect but a feature */
|
||||
EFFECT_TAA_REPROJECT = (1 << 14), /* should be mutually exclusive with EFFECT_TAA */
|
||||
EFFECT_DEPTH_DOUBLE_BUFFER = (1 << 15), /* Not really an effect but a feature */
|
||||
};
|
||||
ENUM_OPERATORS(EEVEE_EffectsFlag, EFFECT_DEPTH_DOUBLE_BUFFER)
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ class Instance {
|
|||
depth_of_field(*this),
|
||||
cryptomatte(*this),
|
||||
hiz_buffer(*this, uniform_data.data.hiz),
|
||||
sampling(*this),
|
||||
sampling(*this, uniform_data.data.clamp),
|
||||
camera(*this, uniform_data.data.camera),
|
||||
film(*this, uniform_data.data.film),
|
||||
render_buffers(*this, uniform_data.data.render_pass),
|
||||
|
|
|
@ -248,6 +248,7 @@ void VolumeProbeModule::set_view(View & /*view*/)
|
|||
if (do_update_world_) {
|
||||
grid_upload_ps_.init();
|
||||
grid_upload_ps_.shader_set(inst_.shaders.static_shader_get(LIGHTPROBE_IRRADIANCE_WORLD));
|
||||
grid_upload_ps_.bind_resources(inst_.uniform_data);
|
||||
grid_upload_ps_.bind_ssbo("harmonic_buf", &inst_.sphere_probes.spherical_harmonics_buf());
|
||||
grid_upload_ps_.bind_ubo("grids_infos_buf", &grids_infos_buf_);
|
||||
grid_upload_ps_.bind_ssbo("bricks_infos_buf", &bricks_infos_buf_);
|
||||
|
@ -364,6 +365,7 @@ void VolumeProbeModule::set_view(View & /*view*/)
|
|||
grid_upload_ps_.init();
|
||||
grid_upload_ps_.shader_set(inst_.shaders.static_shader_get(LIGHTPROBE_IRRADIANCE_LOAD));
|
||||
|
||||
grid_upload_ps_.bind_resources(inst_.uniform_data);
|
||||
grid_upload_ps_.push_constant("validity_threshold", grid->validity_threshold);
|
||||
grid_upload_ps_.push_constant("dilation_threshold", grid->dilation_threshold);
|
||||
grid_upload_ps_.push_constant("dilation_radius", grid->dilation_radius);
|
||||
|
@ -1034,7 +1036,7 @@ void IrradianceBake::surfels_lights_eval()
|
|||
inst_.render_buffers.acquire(int2(1));
|
||||
inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
|
||||
inst_.lights.set_view(view_z_, grid_pixel_extent_.xy());
|
||||
inst_.shadows.set_view(view_z_, inst_.render_buffers.depth_tx);
|
||||
inst_.shadows.set_view(view_z_, grid_pixel_extent_.xy());
|
||||
inst_.render_buffers.release();
|
||||
|
||||
inst_.manager->submit(surfel_light_eval_ps_, view_z_);
|
||||
|
|
|
@ -86,14 +86,6 @@ void LightProbeModule::sync_volume(const Object *ob, ObjectHandle &handle)
|
|||
grid.object_to_world = ob->object_to_world();
|
||||
grid.cache = ob->lightprobe_cache;
|
||||
|
||||
/* Needed for display. */
|
||||
// LightProbeGridCacheFrame *cache = grid.cache ? grid.cache->grid_static_cache : nullptr;
|
||||
// if (cache != nullptr) {
|
||||
// int3 grid_size = int3(cache->size);
|
||||
// /* Offset sample placement so that border texels are on the edges of the volume. */
|
||||
// float3 grid_scale = float3(grid_size) / float3(grid_size + 1);
|
||||
// grid.object_to_world *= math::from_scale<float4x4>(grid_scale);
|
||||
// }
|
||||
grid.world_to_object = float4x4(
|
||||
math::normalize(math::transpose(float3x3(grid.object_to_world))));
|
||||
|
||||
|
@ -150,7 +142,8 @@ void LightProbeModule::sync_sphere(const Object *ob, ObjectHandle &handle)
|
|||
return (bl_shape_type == LIGHTPROBE_SHAPE_BOX) ? SHAPE_CUBOID : SHAPE_ELIPSOID;
|
||||
};
|
||||
cube.influence_shape = to_eevee_shape(light_probe.attenuation_type);
|
||||
cube.parallax_shape = to_eevee_shape(light_probe.parallax_type);
|
||||
cube.parallax_shape = to_eevee_shape(use_custom_parallax ? light_probe.parallax_type :
|
||||
light_probe.attenuation_type);
|
||||
|
||||
float4x4 object_to_world = math::scale(ob->object_to_world(), float3(influence_distance));
|
||||
cube.location = object_to_world.location();
|
||||
|
|
|
@ -403,7 +403,10 @@ PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
|
|||
return pass;
|
||||
}
|
||||
|
||||
void ForwardPipeline::render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb)
|
||||
void ForwardPipeline::render(View &view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &combined_fb,
|
||||
int2 extent)
|
||||
{
|
||||
if (!has_transparent_ && !has_opaque_) {
|
||||
inst_.volume.draw_resolve(view);
|
||||
|
@ -417,7 +420,7 @@ void ForwardPipeline::render(View &view, Framebuffer &prepass_fb, Framebuffer &c
|
|||
|
||||
inst_.hiz_buffer.set_dirty();
|
||||
|
||||
inst_.shadows.set_view(view, inst_.render_buffers.depth_tx);
|
||||
inst_.shadows.set_view(view, extent);
|
||||
inst_.volume_probes.set_view(view);
|
||||
|
||||
if (has_opaque_) {
|
||||
|
@ -528,9 +531,24 @@ void DeferredLayer::begin_sync()
|
|||
this->gbuffer_pass_sync(inst_);
|
||||
}
|
||||
|
||||
void DeferredLayer::end_sync()
|
||||
void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
|
||||
{
|
||||
use_combined_lightprobe_eval = inst_.pipelines.data.use_combined_lightprobe_eval;
|
||||
const SceneEEVEE &sce_eevee = inst_.scene->eevee;
|
||||
const bool has_transmit_closure = (closure_bits_ & (CLOSURE_REFRACTION | CLOSURE_TRANSLUCENT));
|
||||
const bool has_reflect_closure = (closure_bits_ & (CLOSURE_REFLECTION | CLOSURE_DIFFUSE));
|
||||
use_raytracing_ = (has_transmit_closure || has_reflect_closure) &&
|
||||
(sce_eevee.flag & SCE_EEVEE_SSR_ENABLED) != 0;
|
||||
|
||||
use_clamp_direct_ = sce_eevee.clamp_surface_direct != 0.0f;
|
||||
use_clamp_indirect_ = sce_eevee.clamp_surface_indirect != 0.0f;
|
||||
|
||||
/* The first pass will never have any surfaces behind it. Nothing is refracted except the
|
||||
* environment. So in this case, disable tracing and fallback to probe. */
|
||||
use_screen_transmission_ = use_raytracing_ && has_transmit_closure && !is_first_pass;
|
||||
use_screen_reflection_ = use_raytracing_ && has_reflect_closure;
|
||||
|
||||
use_split_radiance_ = use_raytracing_ || (use_clamp_direct_ || use_clamp_indirect_);
|
||||
use_feedback_output_ = use_raytracing_ && (!is_last_pass || use_screen_reflection_);
|
||||
|
||||
{
|
||||
RenderBuffersInfoData &rbuf_data = inst_.render_buffers.data;
|
||||
|
@ -569,6 +587,7 @@ void DeferredLayer::end_sync()
|
|||
pass.init();
|
||||
|
||||
{
|
||||
const bool use_split_indirect = !use_raytracing_ && use_split_radiance_;
|
||||
PassSimple::Sub &sub = pass.sub("Eval.Light");
|
||||
/* Use depth test to reject background pixels which have not been stencil cleared. */
|
||||
/* WORKAROUND: Avoid rasterizer discard by enabling stencil write, but the shaders actually
|
||||
|
@ -585,7 +604,8 @@ void DeferredLayer::end_sync()
|
|||
* OpenGL and Vulkan implementation which aren't fully supporting the specialize
|
||||
* constant. */
|
||||
sub.specialize_constant(sh, "render_pass_shadow_enabled", rbuf_data.shadow_id != -1);
|
||||
sub.specialize_constant(sh, "use_lightprobe_eval", use_combined_lightprobe_eval);
|
||||
sub.specialize_constant(sh, "use_split_indirect", use_split_indirect);
|
||||
sub.specialize_constant(sh, "use_lightprobe_eval", !use_raytracing_);
|
||||
const ShadowSceneData &shadow_scene = inst_.shadows.get_data();
|
||||
sub.specialize_constant(sh, "shadow_ray_count", &shadow_scene.ray_count);
|
||||
sub.specialize_constant(sh, "shadow_ray_step_count", &shadow_scene.step_count);
|
||||
|
@ -593,6 +613,9 @@ void DeferredLayer::end_sync()
|
|||
sub.bind_image("direct_radiance_1_img", &direct_radiance_txs_[0]);
|
||||
sub.bind_image("direct_radiance_2_img", &direct_radiance_txs_[1]);
|
||||
sub.bind_image("direct_radiance_3_img", &direct_radiance_txs_[2]);
|
||||
sub.bind_image("indirect_radiance_1_img", &indirect_result_.closures[0]);
|
||||
sub.bind_image("indirect_radiance_2_img", &indirect_result_.closures[1]);
|
||||
sub.bind_image("indirect_radiance_3_img", &indirect_result_.closures[2]);
|
||||
sub.bind_resources(inst_.uniform_data);
|
||||
sub.bind_resources(inst_.gbuffer);
|
||||
sub.bind_resources(inst_.lights);
|
||||
|
@ -621,8 +644,10 @@ void DeferredLayer::end_sync()
|
|||
"render_pass_specular_light_enabled",
|
||||
(rbuf_data.specular_light_id != -1) ||
|
||||
(rbuf_data.specular_color_id != -1));
|
||||
pass.specialize_constant(sh, "use_split_radiance", use_split_radiance_);
|
||||
pass.specialize_constant(
|
||||
sh, "use_radiance_feedback", use_feedback_output_ && use_clamp_direct_);
|
||||
pass.specialize_constant(sh, "render_pass_normal_enabled", rbuf_data.normal_id != -1);
|
||||
pass.specialize_constant(sh, "use_combined_lightprobe_eval", use_combined_lightprobe_eval);
|
||||
pass.shader_set(sh);
|
||||
/* Use stencil test to reject pixels not written by this layer. */
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL | DRW_STATE_STENCIL_NEQUAL);
|
||||
|
@ -631,11 +656,12 @@ void DeferredLayer::end_sync()
|
|||
pass.bind_texture("direct_radiance_1_tx", &direct_radiance_txs_[0]);
|
||||
pass.bind_texture("direct_radiance_2_tx", &direct_radiance_txs_[1]);
|
||||
pass.bind_texture("direct_radiance_3_tx", &direct_radiance_txs_[2]);
|
||||
pass.bind_texture("indirect_radiance_1_tx", &indirect_radiance_txs_[0]);
|
||||
pass.bind_texture("indirect_radiance_2_tx", &indirect_radiance_txs_[1]);
|
||||
pass.bind_texture("indirect_radiance_3_tx", &indirect_radiance_txs_[2]);
|
||||
pass.bind_texture("indirect_radiance_1_tx", &indirect_result_.closures[0]);
|
||||
pass.bind_texture("indirect_radiance_2_tx", &indirect_result_.closures[1]);
|
||||
pass.bind_texture("indirect_radiance_3_tx", &indirect_result_.closures[2]);
|
||||
pass.bind_image(RBUFS_COLOR_SLOT, &inst_.render_buffers.rp_color_tx);
|
||||
pass.bind_image(RBUFS_VALUE_SLOT, &inst_.render_buffers.rp_value_tx);
|
||||
pass.bind_image("radiance_feedback_img", &radiance_feedback_tx_);
|
||||
pass.bind_resources(inst_.gbuffer);
|
||||
pass.bind_resources(inst_.uniform_data);
|
||||
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
|
@ -675,50 +701,28 @@ PassMain::Sub *DeferredLayer::material_add(::Material *blender_mat, GPUMaterial
|
|||
return &pass->sub(GPU_material_get_name(gpumat));
|
||||
}
|
||||
|
||||
void DeferredLayer::render(View &main_view,
|
||||
View &render_view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &combined_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
int2 extent,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
bool is_first_pass)
|
||||
GPUTexture *DeferredLayer::render(View &main_view,
|
||||
View &render_view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &combined_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
int2 extent,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *radiance_behind_tx)
|
||||
{
|
||||
if (closure_count_ == 0) {
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RenderBuffers &rb = inst_.render_buffers;
|
||||
|
||||
/* The first pass will never have any surfaces behind it. Nothing is refracted except the
|
||||
* environment. So in this case, disable tracing and fallback to probe. */
|
||||
bool do_screen_space_refraction = !is_first_pass &&
|
||||
(closure_bits_ & (CLOSURE_REFRACTION | CLOSURE_TRANSLUCENT));
|
||||
bool do_screen_space_reflection = (closure_bits_ & (CLOSURE_REFLECTION | CLOSURE_DIFFUSE));
|
||||
constexpr eGPUTextureUsage usage_read = GPU_TEXTURE_USAGE_SHADER_READ;
|
||||
constexpr eGPUTextureUsage usage_write = GPU_TEXTURE_USAGE_SHADER_WRITE;
|
||||
constexpr eGPUTextureUsage usage_rw = usage_read | usage_write;
|
||||
|
||||
if (do_screen_space_reflection) {
|
||||
if (radiance_feedback_tx_.ensure_2d(rb.color_format, extent, usage_read)) {
|
||||
radiance_feedback_tx_.clear(float4(0.0));
|
||||
radiance_feedback_persmat_ = render_view.persmat();
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Dummy texture. Will not be used. */
|
||||
radiance_feedback_tx_.ensure_2d(rb.color_format, int2(1), GPU_TEXTURE_USAGE_SHADER_READ);
|
||||
}
|
||||
|
||||
if (do_screen_space_refraction) {
|
||||
if (use_screen_transmission_) {
|
||||
/* Update for refraction. */
|
||||
inst_.hiz_buffer.update();
|
||||
radiance_behind_tx_.ensure_2d(rb.color_format, extent, usage_read);
|
||||
GPU_texture_copy(radiance_behind_tx_, rb.combined_tx);
|
||||
}
|
||||
else {
|
||||
/* Dummy texture. Will not be used. */
|
||||
radiance_behind_tx_.ensure_2d(rb.color_format, int2(1), GPU_TEXTURE_USAGE_SHADER_READ);
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(prepass_fb);
|
||||
|
@ -729,7 +733,7 @@ void DeferredLayer::render(View &main_view,
|
|||
inst_.hiz_buffer.update();
|
||||
|
||||
inst_.volume_probes.set_view(render_view);
|
||||
inst_.shadows.set_view(render_view, inst_.render_buffers.depth_tx);
|
||||
inst_.shadows.set_view(render_view, extent);
|
||||
|
||||
inst_.gbuffer.bind(gbuffer_fb);
|
||||
inst_.manager->submit(gbuffer_ps_, render_view);
|
||||
|
@ -739,53 +743,48 @@ void DeferredLayer::render(View &main_view,
|
|||
(closure_count_ > i) ? extent : int2(1), DEFERRED_RADIANCE_FORMAT, usage_rw);
|
||||
}
|
||||
|
||||
RayTraceResult indirect_result;
|
||||
|
||||
if (use_combined_lightprobe_eval) {
|
||||
float4 data(0.0f);
|
||||
/* Subsurface writes (black) to that texture. */
|
||||
dummy_black_tx.ensure_2d(RAYTRACE_RADIANCE_FORMAT, int2(1), usage_rw, data);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
indirect_radiance_txs_[i] = dummy_black_tx;
|
||||
}
|
||||
if (use_raytracing_) {
|
||||
indirect_result_ = inst_.raytracing.render(
|
||||
rt_buffer, radiance_behind_tx, closure_bits_, main_view, render_view);
|
||||
}
|
||||
else if (use_split_radiance_) {
|
||||
indirect_result_ = inst_.raytracing.alloc_only(rt_buffer);
|
||||
}
|
||||
else {
|
||||
indirect_result = inst_.raytracing.render(rt_buffer,
|
||||
radiance_behind_tx_,
|
||||
radiance_feedback_tx_,
|
||||
radiance_feedback_persmat_,
|
||||
closure_bits_,
|
||||
main_view,
|
||||
render_view,
|
||||
do_screen_space_refraction);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
indirect_radiance_txs_[i] = indirect_result.closures[i].get();
|
||||
}
|
||||
indirect_result_ = inst_.raytracing.alloc_dummy(rt_buffer);
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(combined_fb);
|
||||
inst_.manager->submit(eval_light_ps_, render_view);
|
||||
|
||||
inst_.subsurface.render(
|
||||
direct_radiance_txs_[0], indirect_radiance_txs_[0], closure_bits_, render_view);
|
||||
direct_radiance_txs_[0], indirect_result_.closures[0], closure_bits_, render_view);
|
||||
|
||||
radiance_feedback_tx_ = rt_buffer.feedback_ensure(!use_feedback_output_, extent);
|
||||
|
||||
if (use_feedback_output_ && use_clamp_direct_) {
|
||||
/* We need to do a copy before the combine pass (otherwise we have a dependency issue) to save
|
||||
* the emission and the previous layer's radiance. */
|
||||
GPU_texture_copy(radiance_feedback_tx_, rb.combined_tx);
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(combined_fb);
|
||||
inst_.manager->submit(combine_ps_);
|
||||
|
||||
if (!use_combined_lightprobe_eval) {
|
||||
indirect_result.release();
|
||||
if (use_feedback_output_ && !use_clamp_direct_) {
|
||||
/* We skip writting the radiance during the combine pass. Do a simple fast copy. */
|
||||
GPU_texture_copy(radiance_feedback_tx_, rb.combined_tx);
|
||||
}
|
||||
|
||||
indirect_result_.release();
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(direct_radiance_txs_); i++) {
|
||||
direct_radiance_txs_[i].release();
|
||||
}
|
||||
|
||||
if (do_screen_space_reflection) {
|
||||
GPU_texture_copy(radiance_feedback_tx_, rb.combined_tx);
|
||||
radiance_feedback_persmat_ = render_view.persmat();
|
||||
}
|
||||
|
||||
inst_.pipelines.deferred.debug_draw(render_view, combined_fb);
|
||||
|
||||
return use_feedback_output_ ? radiance_feedback_tx_ : nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -800,8 +799,7 @@ void DeferredPipeline::begin_sync()
|
|||
{
|
||||
Instance &inst = opaque_layer_.inst_;
|
||||
|
||||
const bool use_raytracing = (inst.scene->eevee.flag & SCE_EEVEE_SSR_ENABLED);
|
||||
inst.pipelines.data.use_combined_lightprobe_eval = !use_raytracing;
|
||||
const bool use_raytracing = (inst.scene->eevee.flag & SCE_EEVEE_SSR_ENABLED) != 0;
|
||||
use_combined_lightprobe_eval = !use_raytracing;
|
||||
|
||||
opaque_layer_.begin_sync();
|
||||
|
@ -810,8 +808,8 @@ void DeferredPipeline::begin_sync()
|
|||
|
||||
void DeferredPipeline::end_sync()
|
||||
{
|
||||
opaque_layer_.end_sync();
|
||||
refraction_layer_.end_sync();
|
||||
opaque_layer_.end_sync(true, refraction_layer_.is_empty());
|
||||
refraction_layer_.end_sync(opaque_layer_.is_empty(), true);
|
||||
|
||||
debug_pass_sync();
|
||||
}
|
||||
|
@ -892,26 +890,28 @@ void DeferredPipeline::render(View &main_view,
|
|||
RayTraceBuffer &rt_buffer_opaque_layer,
|
||||
RayTraceBuffer &rt_buffer_refract_layer)
|
||||
{
|
||||
GPUTexture *feedback_tx = nullptr;
|
||||
|
||||
DRW_stats_group_start("Deferred.Opaque");
|
||||
opaque_layer_.render(main_view,
|
||||
render_view,
|
||||
prepass_fb,
|
||||
combined_fb,
|
||||
gbuffer_fb,
|
||||
extent,
|
||||
rt_buffer_opaque_layer,
|
||||
true);
|
||||
feedback_tx = opaque_layer_.render(main_view,
|
||||
render_view,
|
||||
prepass_fb,
|
||||
combined_fb,
|
||||
gbuffer_fb,
|
||||
extent,
|
||||
rt_buffer_opaque_layer,
|
||||
feedback_tx);
|
||||
DRW_stats_group_end();
|
||||
|
||||
DRW_stats_group_start("Deferred.Refract");
|
||||
refraction_layer_.render(main_view,
|
||||
render_view,
|
||||
prepass_fb,
|
||||
combined_fb,
|
||||
gbuffer_fb,
|
||||
extent,
|
||||
rt_buffer_refract_layer,
|
||||
false);
|
||||
feedback_tx = refraction_layer_.render(main_view,
|
||||
render_view,
|
||||
prepass_fb,
|
||||
combined_fb,
|
||||
gbuffer_fb,
|
||||
extent,
|
||||
rt_buffer_refract_layer,
|
||||
feedback_tx);
|
||||
DRW_stats_group_end();
|
||||
}
|
||||
|
||||
|
@ -1222,8 +1222,10 @@ void DeferredProbePipeline::render(View &view,
|
|||
inst_.manager->submit(opaque_layer_.prepass_ps_, view);
|
||||
|
||||
inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
|
||||
inst_.hiz_buffer.update();
|
||||
|
||||
inst_.lights.set_view(view, extent);
|
||||
inst_.shadows.set_view(view, inst_.render_buffers.depth_tx);
|
||||
inst_.shadows.set_view(view, extent);
|
||||
inst_.volume_probes.set_view(view);
|
||||
|
||||
/* Update for lighting pass. */
|
||||
|
@ -1336,13 +1338,12 @@ void PlanarProbePipeline::render(View &view,
|
|||
/* TODO(fclem): This is the only place where we use the layer source to HiZ.
|
||||
* This is because the texture layer view is still a layer texture. */
|
||||
inst_.hiz_buffer.set_source(&depth_layer_tx, 0);
|
||||
inst_.lights.set_view(view, extent);
|
||||
inst_.shadows.set_view(view, depth_layer_tx);
|
||||
inst_.volume_probes.set_view(view);
|
||||
|
||||
/* Update for lighting pass. */
|
||||
inst_.hiz_buffer.update();
|
||||
|
||||
inst_.lights.set_view(view, extent);
|
||||
inst_.shadows.set_view(view, extent);
|
||||
inst_.volume_probes.set_view(view);
|
||||
|
||||
inst_.gbuffer.bind(gbuffer_fb);
|
||||
inst_.manager->submit(gbuffer_ps_, view);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "draw_shader_shared.hh"
|
||||
|
||||
#include "eevee_lut.hh"
|
||||
#include "eevee_raytrace.hh"
|
||||
#include "eevee_subsurface.hh"
|
||||
|
||||
namespace blender::eevee {
|
||||
|
@ -163,7 +164,7 @@ class ForwardPipeline {
|
|||
::Material *blender_mat,
|
||||
GPUMaterial *gpumat);
|
||||
|
||||
void render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb);
|
||||
void render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb, int2 extent);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -248,9 +249,13 @@ class DeferredLayer : DeferredLayerBase {
|
|||
*/
|
||||
TextureFromPool direct_radiance_txs_[3] = {
|
||||
{"direct_radiance_1"}, {"direct_radiance_2"}, {"direct_radiance_3"}};
|
||||
Texture dummy_black_tx = {"dummy_black_tx"};
|
||||
/* NOTE: Only used when `use_split_radiance` is true. */
|
||||
TextureFromPool indirect_radiance_txs_[3] = {
|
||||
{"indirect_radiance_1"}, {"indirect_radiance_2"}, {"indirect_radiance_3"}};
|
||||
/* Used when there is no indirect radiance buffer. */
|
||||
Texture dummy_black = {"dummy_black"};
|
||||
/* Reference to ray-tracing results. */
|
||||
GPUTexture *indirect_radiance_txs_[3] = {nullptr};
|
||||
GPUTexture *radiance_feedback_tx_ = nullptr;
|
||||
|
||||
/**
|
||||
* Tile texture containing several bool per tile indicating presence of feature.
|
||||
|
@ -258,34 +263,52 @@ class DeferredLayer : DeferredLayerBase {
|
|||
*/
|
||||
Texture tile_mask_tx_ = {"tile_mask_tx_"};
|
||||
|
||||
/* TODO(fclem): This should be a TextureFromPool. */
|
||||
Texture radiance_behind_tx_ = {"radiance_behind_tx"};
|
||||
/* TODO(fclem): This shouldn't be part of the pipeline but of the view. */
|
||||
Texture radiance_feedback_tx_ = {"radiance_feedback_tx"};
|
||||
float4x4 radiance_feedback_persmat_;
|
||||
RayTraceResult indirect_result_;
|
||||
|
||||
bool use_combined_lightprobe_eval = true;
|
||||
bool use_split_radiance_ = true;
|
||||
/* Output radiance from the combine shader instead of copy. Allow passing unclamped result. */
|
||||
bool use_feedback_output_ = false;
|
||||
bool use_raytracing_ = false;
|
||||
bool use_screen_transmission_ = false;
|
||||
bool use_screen_reflection_ = false;
|
||||
bool use_clamp_direct_ = false;
|
||||
bool use_clamp_indirect_ = false;
|
||||
|
||||
public:
|
||||
DeferredLayer(Instance &inst) : inst_(inst){};
|
||||
DeferredLayer(Instance &inst) : inst_(inst)
|
||||
{
|
||||
float4 data(0.0f);
|
||||
dummy_black.ensure_2d(RAYTRACE_RADIANCE_FORMAT,
|
||||
int2(1),
|
||||
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE,
|
||||
data);
|
||||
}
|
||||
|
||||
void begin_sync();
|
||||
void end_sync();
|
||||
void end_sync(bool is_first_pass, bool is_last_pass);
|
||||
|
||||
PassMain::Sub *prepass_add(::Material *blender_mat, GPUMaterial *gpumat, bool has_motion);
|
||||
PassMain::Sub *material_add(::Material *blender_mat, GPUMaterial *gpumat);
|
||||
|
||||
void render(View &main_view,
|
||||
View &render_view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &combined_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
int2 extent,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
bool is_first_pass);
|
||||
bool is_empty() const
|
||||
{
|
||||
return closure_count_ != 0;
|
||||
}
|
||||
|
||||
/* Returns the radiance buffer to feed the next layer. */
|
||||
GPUTexture *render(View &main_view,
|
||||
View &render_view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &combined_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
int2 extent,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *radiance_behind_tx);
|
||||
};
|
||||
|
||||
class DeferredPipeline {
|
||||
friend DeferredLayer;
|
||||
|
||||
private:
|
||||
/* Gbuffer filling passes. We could have an arbitrary number of them but for now we just have
|
||||
* a hardcoded number of them. */
|
||||
|
|
|
@ -30,6 +30,10 @@ void RayTraceModule::init()
|
|||
|
||||
ray_tracing_options_ = sce_eevee.ray_tracing_options;
|
||||
tracing_method_ = RaytraceEEVEE_Method(sce_eevee.ray_tracing_method);
|
||||
|
||||
float4 data(0.0f);
|
||||
radiance_dummy_black_tx_.ensure_2d(
|
||||
RAYTRACE_RADIANCE_FORMAT, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, data);
|
||||
}
|
||||
|
||||
void RayTraceModule::sync()
|
||||
|
@ -323,16 +327,19 @@ void RayTraceModule::debug_draw(View & /*view*/, GPUFrameBuffer * /*view_fb*/) {
|
|||
|
||||
RayTraceResult RayTraceModule::render(RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *screen_radiance_back_tx,
|
||||
GPUTexture *screen_radiance_front_tx,
|
||||
const float4x4 &screen_radiance_persmat,
|
||||
eClosureBits active_closures,
|
||||
/* TODO(fclem): Maybe wrap these two in some other class. */
|
||||
View &main_view,
|
||||
View &render_view,
|
||||
bool do_refraction_tracing)
|
||||
View &render_view)
|
||||
{
|
||||
using namespace blender::math;
|
||||
|
||||
screen_radiance_front_tx_ = rt_buffer.radiance_feedback_tx.is_valid() ?
|
||||
rt_buffer.radiance_feedback_tx :
|
||||
radiance_dummy_black_tx_;
|
||||
screen_radiance_back_tx_ = screen_radiance_back_tx ? screen_radiance_back_tx :
|
||||
screen_radiance_front_tx_;
|
||||
|
||||
RaytraceEEVEE options = ray_tracing_options_;
|
||||
|
||||
bool use_horizon_scan = options.trace_max_roughness < 1.0f;
|
||||
|
@ -386,10 +393,9 @@ RayTraceResult RayTraceModule::render(RayTraceBuffer &rt_buffer,
|
|||
data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
|
||||
|
||||
/* Data for the radiance setup. */
|
||||
data_.brightness_clamp = (options.sample_clamp > 0.0) ? options.sample_clamp : 1e20;
|
||||
data_.resolution_scale = resolution_scale;
|
||||
data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
|
||||
data_.radiance_persmat = screen_radiance_persmat;
|
||||
data_.radiance_persmat = render_view.persmat();
|
||||
data_.full_resolution = extent;
|
||||
data_.full_resolution_inv = 1.0f / float2(extent);
|
||||
|
||||
|
@ -410,26 +416,16 @@ RayTraceResult RayTraceModule::render(RayTraceBuffer &rt_buffer,
|
|||
inst_.manager->submit(tile_classify_ps_);
|
||||
}
|
||||
|
||||
data_.trace_refraction = do_refraction_tracing;
|
||||
data_.trace_refraction = screen_radiance_back_tx != nullptr;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
result.closures[i] = trace(i,
|
||||
(closure_count > i),
|
||||
options,
|
||||
rt_buffer,
|
||||
screen_radiance_back_tx,
|
||||
screen_radiance_front_tx,
|
||||
screen_radiance_persmat,
|
||||
main_view,
|
||||
render_view);
|
||||
result.closures[i] = trace(i, (closure_count > i), options, rt_buffer, main_view, render_view);
|
||||
}
|
||||
|
||||
if (has_active_closure) {
|
||||
if (use_horizon_scan) {
|
||||
DRW_stats_group_start("Horizon Scan");
|
||||
|
||||
screen_radiance_front_tx_ = screen_radiance_front_tx;
|
||||
|
||||
downsampled_in_radiance_tx_.acquire(tracing_res_horizon, RAYTRACE_RADIANCE_FORMAT, usage_rw);
|
||||
downsampled_in_normal_tx_.acquire(tracing_res_horizon, GPU_RGB10_A2, usage_rw);
|
||||
|
||||
|
@ -440,7 +436,7 @@ RayTraceResult RayTraceModule::render(RayTraceBuffer &rt_buffer,
|
|||
horizon_radiance_denoised_tx_[i].acquire(tracing_res_horizon, GPU_RGBA8, usage_rw);
|
||||
}
|
||||
for (int i : IndexRange(3)) {
|
||||
horizon_scan_output_tx_[i] = result.closures[i].get();
|
||||
horizon_scan_output_tx_[i] = result.closures[i];
|
||||
}
|
||||
|
||||
horizon_tracing_dispatch_buf_.clear_to_zero();
|
||||
|
@ -465,6 +461,8 @@ RayTraceResult RayTraceModule::render(RayTraceBuffer &rt_buffer,
|
|||
|
||||
DRW_stats_group_end();
|
||||
|
||||
rt_buffer.history_persmat = render_view.persmat();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -473,9 +471,6 @@ RayTraceResultTexture RayTraceModule::trace(
|
|||
bool active_layer,
|
||||
RaytraceEEVEE options,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *screen_radiance_back_tx,
|
||||
GPUTexture *screen_radiance_front_tx,
|
||||
const float4x4 &screen_radiance_persmat,
|
||||
/* TODO(fclem): Maybe wrap these two in some other class. */
|
||||
View &main_view,
|
||||
View &render_view)
|
||||
|
@ -512,7 +507,6 @@ RayTraceResultTexture RayTraceModule::trace(
|
|||
|
||||
data_.thickness = options.screen_trace_thickness;
|
||||
data_.quality = 1.0f - 0.95f * options.screen_trace_quality;
|
||||
data_.brightness_clamp = (options.sample_clamp > 0.0) ? options.sample_clamp : 1e20;
|
||||
|
||||
float roughness_mask_start = options.trace_max_roughness;
|
||||
float roughness_mask_fade = 0.2f;
|
||||
|
@ -522,7 +516,7 @@ RayTraceResultTexture RayTraceModule::trace(
|
|||
data_.resolution_scale = resolution_scale;
|
||||
data_.resolution_bias = int2(inst_.sampling.rng_2d_get(SAMPLING_RAYTRACE_V) * resolution_scale);
|
||||
data_.history_persmat = denoise_buf->history_persmat;
|
||||
data_.radiance_persmat = screen_radiance_persmat;
|
||||
data_.radiance_persmat = render_view.persmat();
|
||||
data_.full_resolution = extent;
|
||||
data_.full_resolution_inv = 1.0f / float2(extent);
|
||||
data_.skip_denoise = !use_spatial_denoise;
|
||||
|
@ -540,9 +534,6 @@ RayTraceResultTexture RayTraceModule::trace(
|
|||
ray_time_tx_.acquire(tracing_res, RAYTRACE_RAYTIME_FORMAT);
|
||||
ray_radiance_tx_.acquire(tracing_res, RAYTRACE_RADIANCE_FORMAT);
|
||||
|
||||
screen_radiance_front_tx_ = screen_radiance_front_tx;
|
||||
screen_radiance_back_tx_ = screen_radiance_back_tx;
|
||||
|
||||
inst_.manager->submit(generate_ps_, render_view);
|
||||
if (tracing_method_ == RAYTRACE_EEVEE_METHOD_SCREEN) {
|
||||
if (inst_.planar_probes.enabled()) {
|
||||
|
@ -638,6 +629,32 @@ RayTraceResultTexture RayTraceModule::trace(
|
|||
return result;
|
||||
}
|
||||
|
||||
RayTraceResult RayTraceModule::alloc_only(RayTraceBuffer &rt_buffer)
|
||||
{
|
||||
const int2 extent = inst_.film.render_extent_get();
|
||||
eGPUTextureUsage usage_rw = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
|
||||
|
||||
RayTraceResult result;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
|
||||
denoise_buf->denoised_bilateral_tx.acquire(extent, RAYTRACE_RADIANCE_FORMAT, usage_rw);
|
||||
result.closures[i] = {denoise_buf->denoised_bilateral_tx};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RayTraceResult RayTraceModule::alloc_dummy(RayTraceBuffer &rt_buffer)
|
||||
{
|
||||
eGPUTextureUsage usage_rw = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
|
||||
|
||||
RayTraceResult result;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
RayTraceBuffer::DenoiseBuffer *denoise_buf = &rt_buffer.closures[i];
|
||||
denoise_buf->denoised_bilateral_tx.acquire(int2(1), RAYTRACE_RADIANCE_FORMAT, usage_rw);
|
||||
result.closures[i] = {denoise_buf->denoised_bilateral_tx};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
||||
|
|
|
@ -28,7 +28,7 @@ class Instance;
|
|||
* \{ */
|
||||
|
||||
/**
|
||||
* Contain persistent buffer that need to be stored per view, per layer.
|
||||
* Contain persistent buffer that need to be stored per view, per deferred layer.
|
||||
*/
|
||||
struct RayTraceBuffer {
|
||||
/** Set of buffers that need to be allocated for each ray type. */
|
||||
|
@ -54,6 +54,26 @@ struct RayTraceBuffer {
|
|||
* One for each closure. Not to be mistaken with deferred layer type.
|
||||
*/
|
||||
DenoiseBuffer closures[3];
|
||||
|
||||
/**
|
||||
* Radiance feedback of the deferred layer for next sample's reflection or next layer's
|
||||
* transmission.
|
||||
*/
|
||||
Texture radiance_feedback_tx = {"radiance_feedback_tx"};
|
||||
/**
|
||||
* Perspective matrix for which the radiance feedback buffer was recorded.
|
||||
* Can be different from de-noise buffer's history matrix.
|
||||
*/
|
||||
float4x4 history_persmat;
|
||||
|
||||
GPUTexture *feedback_ensure(bool is_dummy, int2 extent)
|
||||
{
|
||||
eGPUTextureUsage usage_rw = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
|
||||
if (radiance_feedback_tx.ensure_2d(GPU_RGBA16F, is_dummy ? int2(1) : extent, usage_rw)) {
|
||||
radiance_feedback_tx.clear(float4(0.0f));
|
||||
}
|
||||
return radiance_feedback_tx;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -65,18 +85,26 @@ class RayTraceResultTexture {
|
|||
private:
|
||||
/** Result is in a temporary texture that needs to be released. */
|
||||
TextureFromPool *result_ = nullptr;
|
||||
/** Value of `result_->tx_` that can be referenced in advance. */
|
||||
GPUTexture *tx_ = nullptr;
|
||||
/** History buffer to swap the temporary texture that does not need to be released. */
|
||||
Texture *history_ = nullptr;
|
||||
|
||||
public:
|
||||
RayTraceResultTexture() = default;
|
||||
RayTraceResultTexture(TextureFromPool &result) : result_(result.ptr()){};
|
||||
RayTraceResultTexture(TextureFromPool &result) : result_(result.ptr()), tx_(result){};
|
||||
RayTraceResultTexture(TextureFromPool &result, Texture &history)
|
||||
: result_(result.ptr()), history_(history.ptr()){};
|
||||
: result_(result.ptr()), tx_(result), history_(history.ptr()){};
|
||||
|
||||
GPUTexture *get()
|
||||
operator GPUTexture *() const
|
||||
{
|
||||
return *result_;
|
||||
BLI_assert(tx_ != nullptr);
|
||||
return tx_;
|
||||
}
|
||||
|
||||
GPUTexture **operator&()
|
||||
{
|
||||
return &tx_;
|
||||
}
|
||||
|
||||
void release()
|
||||
|
@ -186,6 +214,7 @@ class RayTraceModule {
|
|||
GPUTexture *screen_radiance_front_tx_ = nullptr;
|
||||
GPUTexture *screen_radiance_back_tx_ = nullptr;
|
||||
|
||||
Texture radiance_dummy_black_tx_ = {"radiance_dummy_black_tx"};
|
||||
/** Dummy texture when the tracing is disabled. */
|
||||
TextureFromPool dummy_result_tx_ = {"dummy_result_tx"};
|
||||
/** Pointer to `inst_.render_buffers.depth_tx` updated before submission. */
|
||||
|
@ -223,13 +252,20 @@ class RayTraceModule {
|
|||
*/
|
||||
RayTraceResult render(RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *screen_radiance_back_tx,
|
||||
GPUTexture *screen_radiance_front_tx,
|
||||
const float4x4 &screen_radiance_persmat,
|
||||
eClosureBits active_closures,
|
||||
/* TODO(fclem): Maybe wrap these two in some other class. */
|
||||
View &main_view,
|
||||
View &render_view,
|
||||
bool do_refraction_tracing);
|
||||
View &render_view);
|
||||
|
||||
/**
|
||||
* Only allocate the RayTraceResult results buffers to be used by other passes.
|
||||
*/
|
||||
RayTraceResult alloc_only(RayTraceBuffer &rt_buffer);
|
||||
|
||||
/**
|
||||
* Only allocate the RayTraceResult results buffers as dummy texture to ensure correct bindings.
|
||||
*/
|
||||
RayTraceResult alloc_dummy(RayTraceBuffer &rt_buffer);
|
||||
|
||||
void debug_pass_sync();
|
||||
void debug_draw(View &view, GPUFrameBuffer *view_fb);
|
||||
|
@ -239,9 +275,6 @@ class RayTraceModule {
|
|||
bool active_layer,
|
||||
RaytraceEEVEE options,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
GPUTexture *screen_radiance_back_tx,
|
||||
GPUTexture *screen_radiance_front_tx,
|
||||
const float4x4 &screen_radiance_persmat,
|
||||
/* TODO(fclem): Maybe wrap these two in some other class. */
|
||||
View &main_view,
|
||||
View &render_view);
|
||||
|
|
|
@ -34,9 +34,6 @@ void SphereProbeModule::begin_sync()
|
|||
LightProbeModule &light_probes = instance_.light_probes;
|
||||
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&light_probes.world_sphere_);
|
||||
{
|
||||
const RaytraceEEVEE &options = instance_.scene->eevee.ray_tracing_options;
|
||||
float probe_brightness_clamp = (options.sample_clamp > 0.0) ? options.sample_clamp : 1e20;
|
||||
|
||||
GPUShader *shader = instance_.shaders.static_shader_get(SPHERE_PROBE_REMAP);
|
||||
|
||||
PassSimple &pass = remap_ps_;
|
||||
|
@ -50,7 +47,7 @@ void SphereProbeModule::begin_sync()
|
|||
pass.push_constant("probe_coord_packed", reinterpret_cast<int4 *>(&probe_sampling_coord_));
|
||||
pass.push_constant("write_coord_packed", reinterpret_cast<int4 *>(&probe_write_coord_));
|
||||
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_data.atlas_coord));
|
||||
pass.push_constant("probe_brightness_clamp", probe_brightness_clamp);
|
||||
pass.bind_resources(instance_.uniform_data);
|
||||
pass.dispatch(&dispatch_probe_pack_);
|
||||
}
|
||||
{
|
||||
|
@ -85,6 +82,7 @@ void SphereProbeModule::begin_sync()
|
|||
pass.bind_ssbo("reflection_probe_buf", &data_buf_);
|
||||
instance_.volume_probes.bind_resources(pass);
|
||||
instance_.sampling.bind_resources(pass);
|
||||
pass.bind_resources(instance_.uniform_data);
|
||||
pass.dispatch(&dispatch_probe_select_);
|
||||
pass.barrier(GPU_BARRIER_UNIFORM);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,13 @@ void Sampling::init(const Scene *scene)
|
|||
|
||||
/* Only multiply after to have full the full DoF web pattern for each time steps. */
|
||||
sample_count_ *= motion_blur_steps_;
|
||||
|
||||
auto clamp_value_load = [](float value) { return (value > 0.0) ? value : 1e20; };
|
||||
|
||||
clamp_data_.surface_direct = clamp_value_load(scene->eevee.clamp_surface_direct);
|
||||
clamp_data_.surface_indirect = clamp_value_load(scene->eevee.clamp_surface_indirect);
|
||||
clamp_data_.volume_direct = clamp_value_load(scene->eevee.clamp_volume_direct);
|
||||
clamp_data_.volume_indirect = clamp_value_load(scene->eevee.clamp_volume_indirect);
|
||||
}
|
||||
|
||||
void Sampling::init(const Object &probe_object)
|
||||
|
|
|
@ -65,8 +65,10 @@ class Sampling {
|
|||
|
||||
SamplingDataBuf data_;
|
||||
|
||||
ClampData &clamp_data_;
|
||||
|
||||
public:
|
||||
Sampling(Instance &inst) : inst_(inst){};
|
||||
Sampling(Instance &inst, ClampData &clamp_data) : inst_(inst), clamp_data_(clamp_data){};
|
||||
~Sampling(){};
|
||||
|
||||
void init(const Scene *scene);
|
||||
|
|
|
@ -1622,6 +1622,20 @@ BLI_STATIC_ASSERT_ALIGN(HiZData, 16)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Light Clamping
|
||||
* \{ */
|
||||
|
||||
struct ClampData {
|
||||
float surface_direct;
|
||||
float surface_indirect;
|
||||
float volume_direct;
|
||||
float volume_indirect;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(ClampData, 16)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Ray-Tracing
|
||||
* \{ */
|
||||
|
@ -1685,8 +1699,6 @@ struct RayTraceData {
|
|||
int horizon_resolution_scale;
|
||||
/** Determine how fast the sample steps are getting bigger. */
|
||||
float quality;
|
||||
/** Maximum brightness during lighting evaluation. */
|
||||
float brightness_clamp;
|
||||
/** Maximum roughness for which we will trace a ray. */
|
||||
float roughness_mask_scale;
|
||||
float roughness_mask_bias;
|
||||
|
@ -1697,6 +1709,7 @@ struct RayTraceData {
|
|||
/** Closure being ray-traced. */
|
||||
int closure_index;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(RayTraceData, 16)
|
||||
|
||||
|
@ -1821,7 +1834,7 @@ BLI_STATIC_ASSERT_ALIGN(PlanarProbeDisplayData, 16)
|
|||
struct PipelineInfoData {
|
||||
float alpha_hash_scale;
|
||||
bool32_t is_probe_reflection;
|
||||
bool32_t use_combined_lightprobe_eval;
|
||||
float _pad1;
|
||||
float _pad2;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(PipelineInfoData, 16)
|
||||
|
@ -1836,6 +1849,7 @@ BLI_STATIC_ASSERT_ALIGN(PipelineInfoData, 16)
|
|||
struct UniformData {
|
||||
AOData ao;
|
||||
CameraData camera;
|
||||
ClampData clamp;
|
||||
FilmData film;
|
||||
HiZData hiz;
|
||||
RayTraceData raytrace;
|
||||
|
|
|
@ -863,7 +863,9 @@ void ShadowModule::begin_sync()
|
|||
sub.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
|
||||
sub.bind_texture("depth_tx", &src_depth_tx_);
|
||||
sub.push_constant("tilemap_proj_ratio", &data_.tilemap_projection_ratio);
|
||||
sub.push_constant("input_depth_extent", &input_depth_extent_);
|
||||
sub.bind_resources(inst_.lights);
|
||||
sub.bind_resources(inst_.hiz_buffer.front);
|
||||
sub.dispatch(&dispatch_depth_scan_size_);
|
||||
}
|
||||
{
|
||||
|
@ -1357,29 +1359,26 @@ int ShadowModule::max_view_per_tilemap()
|
|||
return max_view_count;
|
||||
}
|
||||
|
||||
void ShadowModule::set_view(View &view, GPUTexture *depth_tx)
|
||||
void ShadowModule::set_view(View &view, int2 extent)
|
||||
{
|
||||
if (enabled_ == false) {
|
||||
/* All lights have been tagged to have no shadow. */
|
||||
return;
|
||||
}
|
||||
|
||||
input_depth_extent_ = extent;
|
||||
|
||||
GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
|
||||
|
||||
src_depth_tx_ = depth_tx;
|
||||
|
||||
int3 target_size(1);
|
||||
GPU_texture_get_mipmap_size(depth_tx, 0, target_size);
|
||||
|
||||
dispatch_depth_scan_size_ = math::divide_ceil(target_size, int3(SHADOW_DEPTH_SCAN_GROUP_SIZE));
|
||||
dispatch_depth_scan_size_ = int3(math::divide_ceil(extent, int2(SHADOW_DEPTH_SCAN_GROUP_SIZE)),
|
||||
1);
|
||||
max_view_per_tilemap_ = max_view_per_tilemap();
|
||||
|
||||
pixel_world_radius_ = screen_pixel_radius(view, int2(target_size));
|
||||
pixel_world_radius_ = screen_pixel_radius(view, extent);
|
||||
data_.tilemap_projection_ratio = tilemap_pixel_radius() / pixel_world_radius_;
|
||||
inst_.uniform_data.push_update();
|
||||
|
||||
usage_tag_fb_resolution_ = math::divide_ceil(int2(target_size),
|
||||
int2(std::exp2(usage_tag_fb_lod_)));
|
||||
usage_tag_fb_resolution_ = math::divide_ceil(extent, int2(std::exp2(usage_tag_fb_lod_)));
|
||||
usage_tag_fb.ensure(usage_tag_fb_resolution_);
|
||||
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_MEMORYLESS;
|
||||
|
|
|
@ -260,6 +260,7 @@ class ShadowModule {
|
|||
int2 usage_tag_fb_resolution_;
|
||||
int usage_tag_fb_lod_ = 5;
|
||||
int max_view_per_tilemap_ = 1;
|
||||
int2 input_depth_extent_;
|
||||
|
||||
/* Statistics that are read back to CPU after a few frame (to avoid stall). */
|
||||
SwapChain<ShadowStatisticsBuf, 5> statistics_buf_;
|
||||
|
@ -349,8 +350,9 @@ class ShadowModule {
|
|||
/* Update all shadow regions visible inside the view.
|
||||
* If called multiple time for the same view, it will only do the depth buffer scanning
|
||||
* to check any new opaque surfaces.
|
||||
* Expect the HiZ buffer to be up to date.
|
||||
* Needs to be called after `LightModule::set_view();`. */
|
||||
void set_view(View &view, GPUTexture *depth_tx = nullptr);
|
||||
void set_view(View &view, int2 extent);
|
||||
|
||||
void debug_end_sync();
|
||||
void debug_draw(View &view, GPUFrameBuffer *view_fb);
|
||||
|
|
|
@ -144,7 +144,7 @@ void ShadingView::render()
|
|||
|
||||
// inst_.lookdev.render_overlay(view_fb_);
|
||||
|
||||
inst_.pipelines.forward.render(render_view_, prepass_fb_, combined_fb_);
|
||||
inst_.pipelines.forward.render(render_view_, prepass_fb_, combined_fb_, extent_);
|
||||
|
||||
render_transparent_pass(rbufs);
|
||||
|
||||
|
@ -176,7 +176,7 @@ void ShadingView::render_transparent_pass(RenderBuffers &rbufs)
|
|||
float4 clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
GPU_framebuffer_bind(transparent_fb_);
|
||||
GPU_framebuffer_clear_color(transparent_fb_, clear_color);
|
||||
inst_.pipelines.forward.render(render_view_, prepass_fb_, transparent_fb_);
|
||||
inst_.pipelines.forward.render(render_view_, prepass_fb_, transparent_fb_, rbufs.extent_get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,9 @@ void VolumeModule::draw_prepass(View &main_view)
|
|||
inst_.pipelines.world_volume.render(main_view);
|
||||
|
||||
volume_view.sync(main_view.viewmat(), winmat_infinite);
|
||||
/* TODO(fclem): The infinite projection matrix makes the culling test unreliable (see #115595).
|
||||
* We need custom culling for these but that's not implemented yet. */
|
||||
volume_view.visibility_test(false);
|
||||
|
||||
if (inst_.pipelines.volume.is_enabled()) {
|
||||
inst_.pipelines.volume.render(volume_view, occupancy_tx_);
|
||||
|
|
|
@ -78,11 +78,9 @@ World::~World()
|
|||
|
||||
void World::sync()
|
||||
{
|
||||
::World *bl_world = inst_.use_studio_light() ? nullptr : inst_.scene->world;
|
||||
|
||||
bool has_update = false;
|
||||
|
||||
if (bl_world) {
|
||||
if (inst_.scene->world != nullptr) {
|
||||
/* Detect world update before overriding it. */
|
||||
WorldHandle wo_handle = inst_.sync.sync_world();
|
||||
has_update = wo_handle.recalc != 0;
|
||||
|
@ -91,8 +89,9 @@ void World::sync()
|
|||
/* Sync volume first since its result can override the surface world. */
|
||||
sync_volume();
|
||||
|
||||
::World *bl_world;
|
||||
if (inst_.use_studio_light()) {
|
||||
has_update = lookdev_world_.sync(LookdevParameters(inst_.v3d));
|
||||
has_update |= lookdev_world_.sync(LookdevParameters(inst_.v3d));
|
||||
bl_world = lookdev_world_.world_get();
|
||||
}
|
||||
else if ((inst_.view_layer->layflag & SCE_LAY_SKY) == 0) {
|
||||
|
|
|
@ -48,40 +48,43 @@ void main()
|
|||
GBufferReader gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_normal_tx, texel);
|
||||
|
||||
vec3 diffuse_color = vec3(0.0);
|
||||
vec3 diffuse_light = vec3(0.0);
|
||||
vec3 diffuse_direct = vec3(0.0);
|
||||
vec3 diffuse_indirect = vec3(0.0);
|
||||
vec3 specular_color = vec3(0.0);
|
||||
vec3 specular_light = vec3(0.0);
|
||||
vec3 specular_direct = vec3(0.0);
|
||||
vec3 specular_indirect = vec3(0.0);
|
||||
vec3 out_direct = vec3(0.0);
|
||||
vec3 out_indirect = vec3(0.0);
|
||||
vec3 average_normal = vec3(0.0);
|
||||
|
||||
out_combined = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < GBUFFER_LAYER_MAX && i < gbuf.closure_count; i++) {
|
||||
ClosureUndetermined cl = gbuffer_closure_get(gbuf, i);
|
||||
if (cl.type == CLOSURE_NONE_ID) {
|
||||
continue;
|
||||
}
|
||||
int layer_index = gbuffer_closure_get_bin_index(gbuf, i);
|
||||
vec3 closure_light = load_radiance_direct(texel, layer_index);
|
||||
vec3 closure_direct_light = load_radiance_direct(texel, layer_index);
|
||||
vec3 closure_indirect_light = vec3(0.0);
|
||||
|
||||
if (!use_combined_lightprobe_eval) {
|
||||
closure_light += load_radiance_indirect(texel, layer_index);
|
||||
if (use_split_radiance) {
|
||||
closure_indirect_light = load_radiance_indirect(texel, layer_index);
|
||||
}
|
||||
|
||||
average_normal += cl.N * reduce_add(cl.color);
|
||||
|
||||
switch (cl.type) {
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
diffuse_color += cl.color;
|
||||
diffuse_light += closure_light;
|
||||
average_normal += cl.N * reduce_add(cl.color);
|
||||
diffuse_direct += closure_direct_light;
|
||||
diffuse_indirect += closure_indirect_light;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
specular_color += cl.color;
|
||||
specular_light += closure_light;
|
||||
average_normal += cl.N * reduce_add(cl.color);
|
||||
break;
|
||||
case CLOSURE_NONE_ID:
|
||||
/* TODO(fclem): Assert. */
|
||||
specular_direct += closure_direct_light;
|
||||
specular_indirect += closure_indirect_light;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -93,16 +96,36 @@ void main()
|
|||
cl.color *= cl.color;
|
||||
}
|
||||
|
||||
closure_light *= cl.color;
|
||||
out_combined.rgb += closure_light;
|
||||
out_direct += closure_direct_light * cl.color;
|
||||
out_indirect += closure_indirect_light * cl.color;
|
||||
}
|
||||
|
||||
if (use_radiance_feedback) {
|
||||
/* Output unmodified radiance for indirect lighting. */
|
||||
vec3 out_radiance = imageLoad(radiance_feedback_img, texel).rgb;
|
||||
out_radiance += out_direct + out_indirect;
|
||||
imageStore(radiance_feedback_img, texel, vec4(out_radiance, 0.0));
|
||||
}
|
||||
|
||||
/* Light clamping. */
|
||||
float clamp_direct = uniform_buf.clamp.surface_direct;
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
out_direct = colorspace_brightness_clamp_max(out_direct, clamp_direct);
|
||||
out_indirect = colorspace_brightness_clamp_max(out_indirect, clamp_indirect);
|
||||
/* TODO(fcleù): Shouldn't we clamp these relative the main clamp? */
|
||||
diffuse_direct = colorspace_brightness_clamp_max(diffuse_direct, clamp_direct);
|
||||
diffuse_indirect = colorspace_brightness_clamp_max(diffuse_indirect, clamp_indirect);
|
||||
specular_direct = colorspace_brightness_clamp_max(specular_direct, clamp_direct);
|
||||
specular_indirect = colorspace_brightness_clamp_max(specular_indirect, clamp_indirect);
|
||||
|
||||
/* Light passes. */
|
||||
if (render_pass_diffuse_light_enabled) {
|
||||
vec3 diffuse_light = diffuse_direct + diffuse_indirect;
|
||||
output_renderpass_color(uniform_buf.render_pass.diffuse_color_id, vec4(diffuse_color, 1.0));
|
||||
output_renderpass_color(uniform_buf.render_pass.diffuse_light_id, vec4(diffuse_light, 1.0));
|
||||
}
|
||||
if (render_pass_specular_light_enabled) {
|
||||
vec3 specular_light = specular_direct + specular_indirect;
|
||||
output_renderpass_color(uniform_buf.render_pass.specular_color_id, vec4(specular_color, 1.0));
|
||||
output_renderpass_color(uniform_buf.render_pass.specular_light_id, vec4(specular_light, 1.0));
|
||||
}
|
||||
|
@ -113,9 +136,7 @@ void main()
|
|||
output_renderpass_color(uniform_buf.render_pass.normal_id, vec4(average_normal, 1.0));
|
||||
}
|
||||
|
||||
if (any(isnan(out_combined))) {
|
||||
out_combined = vec4(1.0, 0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
out_combined = vec4(out_direct + out_indirect, 0.0);
|
||||
out_combined = any(isnan(out_combined)) ? vec4(1.0, 0.0, 1.0, 0.0) : out_combined;
|
||||
out_combined = colorspace_safe_color(out_combined);
|
||||
}
|
||||
|
|
|
@ -91,9 +91,29 @@ void main()
|
|||
if (use_lightprobe_eval) {
|
||||
LightProbeSample samp = lightprobe_load(P, Ng, V);
|
||||
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
|
||||
|
||||
for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT && i < gbuf.closure_count; i++) {
|
||||
ClosureUndetermined cl = gbuffer_closure_get(gbuf, i);
|
||||
lightprobe_eval(samp, cl, P, V, gbuf.thickness, stack.cl[i].light_shadowed);
|
||||
vec3 indirect_light = lightprobe_eval(samp, cl, P, V, gbuf.thickness);
|
||||
|
||||
if (use_split_indirect) {
|
||||
int layer_index = gbuffer_closure_get_bin_index(gbuf, i);
|
||||
/* TODO(fclem): Layered texture. */
|
||||
if (layer_index == 0) {
|
||||
imageStore(indirect_radiance_1_img, texel, vec4(indirect_light, 1.0));
|
||||
}
|
||||
else if (layer_index == 1) {
|
||||
imageStore(indirect_radiance_2_img, texel, vec4(indirect_light, 1.0));
|
||||
}
|
||||
else if (layer_index == 2) {
|
||||
imageStore(indirect_radiance_3_img, texel, vec4(indirect_light, 1.0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
stack.cl[i].light_shadowed += indirect_light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#pragma BLENDER_REQUIRE(eevee_subsurface_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
|
||||
|
||||
#if CLOSURE_BIN_COUNT != LIGHT_CLOSURE_EVAL_COUNT
|
||||
# error Closure data count and eval count must match
|
||||
|
@ -64,21 +65,37 @@ void forward_lighting_eval(float thickness, out vec3 radiance, out vec3 transmit
|
|||
|
||||
LightProbeSample samp = lightprobe_load(g_data.P, g_data.Ng, V);
|
||||
|
||||
float clamp_indirect_sh = uniform_buf.clamp.surface_indirect;
|
||||
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect_sh);
|
||||
|
||||
/* Combine all radiance. */
|
||||
radiance = g_emission;
|
||||
vec3 radiance_direct = vec3(0.0);
|
||||
vec3 radiance_indirect = vec3(0.0);
|
||||
for (int i = 0; i < LIGHT_CLOSURE_EVAL_COUNT; i++) {
|
||||
ClosureUndetermined cl = g_closure_get(i);
|
||||
lightprobe_eval(samp, cl, g_data.P, V, thickness, stack.cl[i].light_shadowed);
|
||||
if (cl.weight > 1e-5) {
|
||||
vec3 direct_light = stack.cl[i].light_shadowed;
|
||||
vec3 indirect_light = lightprobe_eval(samp, cl, g_data.P, V, thickness);
|
||||
|
||||
if ((cl.type == CLOSURE_BSDF_TRANSLUCENT_ID ||
|
||||
cl.type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) &&
|
||||
(thickness > 0.0))
|
||||
{
|
||||
/* We model two transmission event, so the surface color need to be applied twice. */
|
||||
stack.cl[i].light_shadowed *= cl.color;
|
||||
cl.color *= cl.color;
|
||||
}
|
||||
radiance += stack.cl[i].light_shadowed * cl.color * cl.weight;
|
||||
cl.color *= cl.weight;
|
||||
|
||||
radiance_direct += direct_light * cl.color;
|
||||
radiance_indirect += indirect_light * cl.color;
|
||||
}
|
||||
}
|
||||
/* Light clamping. */
|
||||
float clamp_direct = uniform_buf.clamp.surface_direct;
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
radiance_direct = colorspace_brightness_clamp_max(radiance_direct, clamp_direct);
|
||||
radiance_indirect = colorspace_brightness_clamp_max(radiance_indirect, clamp_indirect);
|
||||
|
||||
radiance = radiance_direct + radiance_indirect + g_emission;
|
||||
transmittance = g_transmittance;
|
||||
}
|
||||
|
|
|
@ -411,31 +411,32 @@ void gbuffer_skip_data(inout GBufferReader gbuf)
|
|||
|
||||
/**
|
||||
* Set the dedicated normal bit for the last added closure.
|
||||
* Expects `layer_id` to be in [0..2].
|
||||
* Expects `bin_id` to be in [0..2].
|
||||
* Expects `normal_id` to be in [0..3].
|
||||
*/
|
||||
void gbuffer_header_normal_layer_id_set(inout uint header, int layer_id, uint normal_id)
|
||||
void gbuffer_header_normal_layer_id_set(inout uint header, int bin_id, uint normal_id)
|
||||
{
|
||||
/* Layer 0 will always have normal id 0. It doesn't have to be encoded. Skip it. */
|
||||
if (layer_id == 0) {
|
||||
if (bin_id == 0) {
|
||||
return;
|
||||
}
|
||||
/* -2 is to skip the layer_id 0 and start encoding for layer_id 1. This keeps the FMA. */
|
||||
header |= normal_id << ((GBUFFER_NORMAL_BITS_SHIFT - 2) + layer_id * 2);
|
||||
/* -2 is to skip the bin_id 0 and start encoding for bin_id 1. This keeps the FMA. */
|
||||
header |= normal_id << ((GBUFFER_NORMAL_BITS_SHIFT - 2) + bin_id * 2);
|
||||
}
|
||||
int gbuffer_header_normal_layer_id_get(uint header, int layer_id)
|
||||
int gbuffer_header_normal_layer_id_get(uint header, int bin_id)
|
||||
{
|
||||
/* Layer 0 will always have normal id 0. */
|
||||
if (layer_id == 0) {
|
||||
if (bin_id == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* -2 is to skip the layer_id 0 and start encoding for layer_id 1. This keeps the FMA. */
|
||||
return int(3u & (header >> ((GBUFFER_NORMAL_BITS_SHIFT - 2) + layer_id * 2)));
|
||||
/* -2 is to skip the bin_id 0 and start encoding for bin_id 1. This keeps the FMA. */
|
||||
return int(3u & (header >> ((GBUFFER_NORMAL_BITS_SHIFT - 2) + bin_id * 2)));
|
||||
}
|
||||
|
||||
void gbuffer_append_normal(inout GBufferWriter gbuf, vec3 normal)
|
||||
{
|
||||
vec2 packed_N = gbuffer_normal_pack(normal);
|
||||
/* Assumes this function is called after gbuffer_append_closure. */
|
||||
int layer_id = gbuf.bins_len - 1;
|
||||
/* Try to reuse previous normals. */
|
||||
#if GBUFFER_NORMAL_MAX > 1
|
||||
|
@ -478,9 +479,9 @@ void gbuffer_append_normal(inout GBufferWriter gbuf, vec3 normal)
|
|||
}
|
||||
gbuf.normal_len++;
|
||||
}
|
||||
vec3 gbuffer_normal_get(inout GBufferReader gbuf, int layer_id, samplerGBufferNormal normal_tx)
|
||||
vec3 gbuffer_normal_get(inout GBufferReader gbuf, int bin_id, samplerGBufferNormal normal_tx)
|
||||
{
|
||||
int normal_layer_id = gbuffer_header_normal_layer_id_get(gbuf.header, layer_id);
|
||||
int normal_layer_id = gbuffer_header_normal_layer_id_get(gbuf.header, bin_id);
|
||||
vec2 normal_packed = fetchGBuffer(normal_tx, gbuf.texel, normal_layer_id).rg;
|
||||
gbuf.normal_len = max(gbuf.normal_len, normal_layer_id + 1);
|
||||
return gbuffer_normal_unpack(normal_packed);
|
||||
|
@ -534,6 +535,7 @@ void gbuffer_closure_diffuse_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_diffuse_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -541,7 +543,7 @@ void gbuffer_closure_diffuse_load(inout GBufferReader gbuf,
|
|||
|
||||
ClosureUndetermined cl = closure_new(CLOSURE_BSDF_DIFFUSE_ID);
|
||||
cl.color = gbuffer_closure_color_unpack(data0);
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -560,6 +562,7 @@ void gbuffer_closure_translucent_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_translucent_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -567,7 +570,7 @@ void gbuffer_closure_translucent_load(inout GBufferReader gbuf,
|
|||
|
||||
ClosureUndetermined cl = closure_new(CLOSURE_BSDF_TRANSLUCENT_ID);
|
||||
cl.color = gbuffer_closure_color_unpack(data0);
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -588,6 +591,7 @@ void gbuffer_closure_subsurface_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_subsurface_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -597,7 +601,7 @@ void gbuffer_closure_subsurface_load(inout GBufferReader gbuf,
|
|||
ClosureUndetermined cl = closure_new(CLOSURE_BSSRDF_BURLEY_ID);
|
||||
cl.color = gbuffer_closure_color_unpack(data0);
|
||||
cl.data.rgb = gbuffer_sss_radii_unpack(data1);
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -618,6 +622,7 @@ void gbuffer_closure_reflection_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_reflection_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -627,7 +632,7 @@ void gbuffer_closure_reflection_load(inout GBufferReader gbuf,
|
|||
ClosureUndetermined cl = closure_new(CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID);
|
||||
cl.color = gbuffer_closure_color_unpack(data0);
|
||||
cl.data.x = data1.x;
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -648,6 +653,7 @@ void gbuffer_closure_refraction_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_refraction_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -658,7 +664,7 @@ void gbuffer_closure_refraction_load(inout GBufferReader gbuf,
|
|||
cl.color = gbuffer_closure_color_unpack(data0);
|
||||
cl.data.x = data1.x;
|
||||
cl.data.y = gbuffer_ior_unpack(data1.y);
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -686,6 +692,7 @@ void gbuffer_closure_reflection_colorless_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_reflection_colorless_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -695,7 +702,7 @@ void gbuffer_closure_reflection_colorless_load(inout GBufferReader gbuf,
|
|||
cl.data.x = data0.x;
|
||||
cl.color = vec3(gbuffer_closure_intensity_unpack(data0.zw));
|
||||
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -715,6 +722,7 @@ void gbuffer_closure_refraction_colorless_skip(inout GBufferReader gbuf)
|
|||
}
|
||||
void gbuffer_closure_refraction_colorless_load(inout GBufferReader gbuf,
|
||||
int layer,
|
||||
int bin_index,
|
||||
samplerGBufferClosure closure_tx,
|
||||
samplerGBufferNormal normal_tx)
|
||||
{
|
||||
|
@ -725,7 +733,7 @@ void gbuffer_closure_refraction_colorless_load(inout GBufferReader gbuf,
|
|||
cl.data.y = gbuffer_ior_unpack(data0.y);
|
||||
cl.color = vec3(gbuffer_closure_intensity_unpack(data0.zw));
|
||||
|
||||
cl.N = gbuffer_normal_get(gbuf, layer, normal_tx);
|
||||
cl.N = gbuffer_normal_get(gbuf, bin_index, normal_tx);
|
||||
|
||||
gbuffer_register_closure(gbuf, cl, layer);
|
||||
}
|
||||
|
@ -831,6 +839,9 @@ GBufferWriter gbuffer_pack(GBufferData data_in)
|
|||
}
|
||||
has_additional_data = true;
|
||||
break;
|
||||
default:
|
||||
gbuf.bins_len++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -881,19 +892,6 @@ ClosureType gbuffer_closure_type_get_by_bin(uint header, int bin_index)
|
|||
return gbuffer_mode_to_closure_type(mode);
|
||||
}
|
||||
|
||||
/* Only read closure types out of the header. The rest of GBufferReader is undefined. */
|
||||
GBufferReader gbuffer_read_header_closure_types(uint header)
|
||||
{
|
||||
GBufferReader gbuf;
|
||||
|
||||
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
|
||||
GBufferMode mode = gbuffer_header_unpack(header, bin);
|
||||
ClosureType closure_type = gbuffer_mode_to_closure_type(mode);
|
||||
gbuffer_register_closure(gbuf, closure_new(closure_type), bin);
|
||||
}
|
||||
return gbuf;
|
||||
}
|
||||
|
||||
/* Return the bin index of a closure using its layer index. */
|
||||
int gbuffer_closure_get_bin_index(GBufferReader gbuf, int layer_index)
|
||||
{
|
||||
|
@ -965,34 +963,36 @@ GBufferReader gbuffer_read(samplerGBufferHeader header_tx,
|
|||
case GBUF_NONE:
|
||||
break;
|
||||
case GBUF_DIFFUSE:
|
||||
gbuffer_closure_diffuse_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_diffuse_load(gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
break;
|
||||
case GBUF_TRANSLUCENT:
|
||||
gbuffer_closure_translucent_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_translucent_load(gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
has_additional_data = true;
|
||||
break;
|
||||
case GBUF_SUBSURFACE:
|
||||
gbuffer_closure_subsurface_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_subsurface_load(gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
has_additional_data = true;
|
||||
break;
|
||||
case GBUF_REFLECTION:
|
||||
gbuffer_closure_reflection_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_reflection_load(gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
break;
|
||||
case GBUF_REFRACTION:
|
||||
gbuffer_closure_refraction_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_refraction_load(gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
has_additional_data = true;
|
||||
break;
|
||||
case GBUF_REFLECTION_COLORLESS:
|
||||
gbuffer_closure_reflection_colorless_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_reflection_colorless_load(
|
||||
gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
break;
|
||||
case GBUF_REFRACTION_COLORLESS:
|
||||
gbuffer_closure_refraction_colorless_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_refraction_colorless_load(
|
||||
gbuf, gbuf.closure_count, bin, closure_tx, normal_tx);
|
||||
gbuf.closure_count++;
|
||||
has_additional_data = true;
|
||||
break;
|
||||
|
@ -1028,7 +1028,7 @@ ClosureUndetermined gbuffer_read_bin(uint header,
|
|||
for (int bin = 0; bin < GBUFFER_LAYER_MAX; bin++) {
|
||||
mode = gbuffer_header_unpack(gbuf.header, bin);
|
||||
|
||||
if (mode != GBUF_NONE && bin >= bin_index) {
|
||||
if (bin >= bin_index) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1066,25 +1066,27 @@ ClosureUndetermined gbuffer_read_bin(uint header,
|
|||
gbuffer_register_closure(gbuf, closure_new(CLOSURE_NONE_ID), gbuf.closure_count);
|
||||
break;
|
||||
case GBUF_DIFFUSE:
|
||||
gbuffer_closure_diffuse_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_diffuse_load(gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_TRANSLUCENT:
|
||||
gbuffer_closure_translucent_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_translucent_load(gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_SUBSURFACE:
|
||||
gbuffer_closure_subsurface_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_subsurface_load(gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_REFLECTION:
|
||||
gbuffer_closure_reflection_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_reflection_load(gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_REFRACTION:
|
||||
gbuffer_closure_refraction_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_refraction_load(gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_REFLECTION_COLORLESS:
|
||||
gbuffer_closure_reflection_colorless_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_reflection_colorless_load(
|
||||
gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
case GBUF_REFRACTION_COLORLESS:
|
||||
gbuffer_closure_refraction_colorless_load(gbuf, gbuf.closure_count, closure_tx, normal_tx);
|
||||
gbuffer_closure_refraction_colorless_load(
|
||||
gbuf, gbuf.closure_count, bin_index, closure_tx, normal_tx);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,11 @@ void main()
|
|||
cl3.color = vec3(1);
|
||||
cl3.N = normalize(vec3(0.3, 0.2, 0.1));
|
||||
|
||||
ClosureUndetermined cl_none = closure_new(CLOSURE_NONE);
|
||||
cl_none.weight = 1.0;
|
||||
cl_none.color = vec3(1);
|
||||
cl_none.N = normalize(vec3(0.0, 0.0, 1.0));
|
||||
|
||||
TEST(eevee_gbuffer, NormalReuseDoubleFirst)
|
||||
{
|
||||
data_in = gbuffer_new();
|
||||
|
@ -228,4 +233,43 @@ void main()
|
|||
EXPECT_NEAR(cl2.N, gbuffer_closure_get(data_out, 1).N, 1e-5);
|
||||
EXPECT_NEAR(cl3.N, gbuffer_closure_get(data_out, 2).N, 1e-5);
|
||||
}
|
||||
|
||||
TEST(eevee_gbuffer, NormalReuseSingleHole)
|
||||
{
|
||||
data_in = gbuffer_new();
|
||||
data_in.closure[0] = cl1;
|
||||
data_in.closure[1] = cl_none;
|
||||
data_in.closure[2] = cl3;
|
||||
|
||||
g_data_packed = gbuffer_pack(data_in);
|
||||
|
||||
EXPECT_EQ(g_data_packed.normal_len, 2);
|
||||
|
||||
data_out = gbuffer_read(header_tx, closure_tx, normal_tx, ivec2(0));
|
||||
|
||||
EXPECT_EQ(data_out.closure_count, 2);
|
||||
EXPECT_EQ(data_out.normal_len, 2);
|
||||
EXPECT_NEAR(cl1.N, gbuffer_closure_get(data_out, 0).N, 1e-5);
|
||||
EXPECT_NEAR(cl3.N, gbuffer_closure_get(data_out, 1).N, 1e-5);
|
||||
EXPECT_NEAR(cl3.N, gbuffer_closure_get_by_bin(data_out, 2).N, 1e-5);
|
||||
}
|
||||
|
||||
TEST(eevee_gbuffer, NormalReuseDoubleHole)
|
||||
{
|
||||
data_in = gbuffer_new();
|
||||
data_in.closure[0] = cl_none;
|
||||
data_in.closure[1] = cl_none;
|
||||
data_in.closure[2] = cl3;
|
||||
|
||||
g_data_packed = gbuffer_pack(data_in);
|
||||
|
||||
EXPECT_EQ(g_data_packed.normal_len, 1);
|
||||
|
||||
data_out = gbuffer_read(header_tx, closure_tx, normal_tx, ivec2(0));
|
||||
|
||||
EXPECT_EQ(data_out.closure_count, 1);
|
||||
EXPECT_EQ(data_out.normal_len, 1);
|
||||
EXPECT_NEAR(cl3.N, gbuffer_closure_get(data_out, 0).N, 1e-5);
|
||||
EXPECT_NEAR(cl3.N, gbuffer_closure_get_by_bin(data_out, 2).N, 1e-5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,9 @@ void main()
|
|||
|
||||
LightProbeSample samp = lightprobe_load(P, Ng, V);
|
||||
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
|
||||
|
||||
for (int i = 0; i < GBUFFER_LAYER_MAX && i < gbuf.closure_count; i++) {
|
||||
ClosureUndetermined cl = gbuffer_closure_get(gbuf, i);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ void main()
|
|||
vec3 ssP_prev = drw_ndc_to_screen(project_point(uniform_buf.raytrace.radiance_persmat, P));
|
||||
|
||||
vec4 radiance = texture(in_radiance_tx, ssP_prev.xy);
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.raytrace.brightness_clamp);
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.clamp.surface_indirect);
|
||||
|
||||
imageStore(out_radiance_img, texel, radiance);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ vec3 lightprobe_spherical_sample_normalized_with_parallax(
|
|||
{
|
||||
SphereProbeData probe = reflection_probe_buf[probe_index];
|
||||
ReflectionProbeLowFreqLight shading_sh = reflection_probes_extract_low_freq(P_sh);
|
||||
vec3 normalization_factor = reflection_probes_normalization_eval(
|
||||
float normalization_factor = reflection_probes_normalization_eval(
|
||||
L, shading_sh, probe.low_freq_light);
|
||||
L = lightprobe_sphere_parallax(probe, P, L);
|
||||
return normalization_factor * reflection_probes_sample(L, lod, probe.atlas_coord).rgb;
|
||||
|
@ -139,32 +139,23 @@ vec3 lightprobe_eval(LightProbeSample samp, ClosureRefraction cl, vec3 P, vec3 V
|
|||
return mix(radiance_cube, radiance_sh, fac);
|
||||
}
|
||||
|
||||
void lightprobe_eval(LightProbeSample samp,
|
||||
ClosureUndetermined cl,
|
||||
vec3 P,
|
||||
vec3 V,
|
||||
float thickness,
|
||||
inout vec3 radiance)
|
||||
vec3 lightprobe_eval(
|
||||
LightProbeSample samp, ClosureUndetermined cl, vec3 P, vec3 V, float thickness)
|
||||
{
|
||||
switch (cl.type) {
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
radiance += lightprobe_eval(samp, to_closure_translucent(cl), P, V, thickness);
|
||||
break;
|
||||
return lightprobe_eval(samp, to_closure_translucent(cl), P, V, thickness);
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
/* TODO: Support translucency in ray tracing first. Otherwise we have a discrepancy. */
|
||||
return vec3(0.0);
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
radiance += lightprobe_eval(samp, to_closure_diffuse(cl), P, V);
|
||||
break;
|
||||
return lightprobe_eval(samp, to_closure_diffuse(cl), P, V);
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID:
|
||||
radiance += lightprobe_eval(samp, to_closure_reflection(cl), P, V);
|
||||
break;
|
||||
return lightprobe_eval(samp, to_closure_reflection(cl), P, V);
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
radiance += lightprobe_eval(samp, to_closure_refraction(cl), P, V, thickness);
|
||||
break;
|
||||
case CLOSURE_NONE_ID:
|
||||
/* TODO(fclem): Assert. */
|
||||
break;
|
||||
return lightprobe_eval(samp, to_closure_refraction(cl), P, V, thickness);
|
||||
}
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
#endif /* SPHERE_PROBE */
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_ray_types_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_ray_trace_screen_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_spherical_harmonics_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -60,12 +61,16 @@ void main()
|
|||
* direction over many rays. */
|
||||
vec3 Ng = ray.direction;
|
||||
LightProbeSample samp = lightprobe_load(ray.origin, Ng, V);
|
||||
/* Clamp SH to have parity with forward evaluation. */
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
|
||||
|
||||
vec3 radiance = lightprobe_eval_direction(
|
||||
samp, ray.origin, ray.direction, safe_rcp(ray_pdf_inv));
|
||||
/* Set point really far for correct reprojection of background. */
|
||||
float hit_time = 1000.0;
|
||||
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.raytrace.brightness_clamp);
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.clamp.surface_indirect);
|
||||
|
||||
imageStore(ray_time_img, texel, vec4(hit_time));
|
||||
imageStore(ray_radiance_img, texel, vec4(radiance, 0.0));
|
||||
|
|
|
@ -87,11 +87,6 @@ void main()
|
|||
if (hit.valid) {
|
||||
/* Evaluate radiance at hit-point. */
|
||||
radiance = textureLod(planar_radiance_tx, vec3(hit.ss_hit_P.xy, planar_id), 0.0).rgb;
|
||||
|
||||
/* Transmit twice if thickness is set and ray is longer than thickness. */
|
||||
// if (thickness > 0.0 && length(ray_data.xyz) > thickness) {
|
||||
// ray_radiance.rgb *= color;
|
||||
// }
|
||||
}
|
||||
else {
|
||||
/* Using ray direction as geometric normal to bias the sampling position.
|
||||
|
@ -105,7 +100,7 @@ void main()
|
|||
hit.time = 10000.0;
|
||||
}
|
||||
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.raytrace.brightness_clamp);
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.clamp.surface_indirect);
|
||||
|
||||
imageStore(ray_time_img, texel, vec4(hit.time));
|
||||
imageStore(ray_radiance_img, texel, vec4(radiance, 0.0));
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_ray_types_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_ray_trace_screen_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_spherical_harmonics_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -131,12 +132,16 @@ void main()
|
|||
vec3 Ng = ray.direction;
|
||||
/* Fallback to nearest light-probe. */
|
||||
LightProbeSample samp = lightprobe_load(ray.origin, Ng, V);
|
||||
/* Clamp SH to have parity with forward evaluation. */
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
samp.volume_irradiance = spherical_harmonics_clamp(samp.volume_irradiance, clamp_indirect);
|
||||
|
||||
radiance = lightprobe_eval_direction(samp, ray.origin, ray.direction, safe_rcp(ray_pdf_inv));
|
||||
/* Set point really far for correct reprojection of background. */
|
||||
hit.time = 10000.0;
|
||||
}
|
||||
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.raytrace.brightness_clamp);
|
||||
radiance = colorspace_brightness_clamp_max(radiance, uniform_buf.clamp.surface_indirect);
|
||||
|
||||
imageStore(ray_time_img, texel, vec4(hit.time));
|
||||
imageStore(ray_radiance_img, texel, vec4(radiance, 0.0));
|
||||
|
|
|
@ -40,11 +40,11 @@ ReflectionProbeLowFreqLight reflection_probes_extract_low_freq(SphericalHarmonic
|
|||
return result;
|
||||
}
|
||||
|
||||
vec3 reflection_probes_normalization_eval(vec3 L,
|
||||
ReflectionProbeLowFreqLight numerator,
|
||||
ReflectionProbeLowFreqLight denominator)
|
||||
float reflection_probes_normalization_eval(vec3 L,
|
||||
ReflectionProbeLowFreqLight numerator,
|
||||
ReflectionProbeLowFreqLight denominator)
|
||||
{
|
||||
/* TODO(fclem): Adjusting directionality is tricky.
|
||||
* Needs to be revisited later on. For now only use the ambient term. */
|
||||
return vec3(numerator.ambient * safe_rcp(denominator.ambient));
|
||||
return (numerator.ambient * safe_rcp(denominator.ambient));
|
||||
}
|
||||
|
|
|
@ -89,11 +89,12 @@ void main()
|
|||
radiance.rgb = mix(world_radiance.rgb, radiance.rgb, opacity);
|
||||
}
|
||||
|
||||
radiance = colorspace_brightness_clamp_max(radiance, probe_brightness_clamp);
|
||||
|
||||
if (!any(greaterThanEqual(local_texel, ivec2(write_coord.extent)))) {
|
||||
float clamp_indirect = uniform_buf.clamp.surface_indirect;
|
||||
vec3 out_radiance = colorspace_brightness_clamp_max(radiance, clamp_indirect);
|
||||
|
||||
ivec3 texel = ivec3(local_texel + write_coord.offset, write_coord.layer);
|
||||
imageStore(atlas_img, texel, vec4(radiance, 1.0));
|
||||
imageStore(atlas_img, texel, vec4(out_radiance, 1.0));
|
||||
}
|
||||
|
||||
if (extract_sh) {
|
||||
|
|
|
@ -26,5 +26,8 @@ void main()
|
|||
sh = lightprobe_irradiance_sample(probe_center);
|
||||
}
|
||||
|
||||
float clamp_indirect_sh = uniform_buf.clamp.surface_indirect;
|
||||
sh = spherical_harmonics_clamp(sh, clamp_indirect_sh);
|
||||
|
||||
reflection_probe_buf[idx].low_freq_light = reflection_probes_extract_low_freq(sh);
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 tex_size = textureSize(depth_tx, 0).xy;
|
||||
ivec2 tex_size = input_depth_extent;
|
||||
|
||||
if (!in_range_inclusive(texel, ivec2(0), ivec2(tex_size - 1))) {
|
||||
return;
|
||||
}
|
||||
|
||||
float depth = texelFetch(depth_tx, texel, 0).r;
|
||||
float depth = texelFetch(hiz_tx, texel, 0).r;
|
||||
if (depth == 1.0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -707,3 +707,29 @@ SphericalHarmonicL1 spherical_harmonics_decompress(SphericalHarmonicL1 sh)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Clamping
|
||||
*
|
||||
* Clamp the total power of the SH function.
|
||||
* \{ */
|
||||
|
||||
SphericalHarmonicL1 spherical_harmonics_clamp(SphericalHarmonicL1 sh, float clamp_value)
|
||||
{
|
||||
/* Convert coefficients to per channel column. */
|
||||
mat4x4 per_channel = transpose(mat4x4(sh.L0.M0, sh.L1.Mn1, sh.L1.M0, sh.L1.Mp1));
|
||||
/* Maximum per channel. */
|
||||
vec3 max_L1 = vec3(reduce_max(abs(per_channel[0].yzw)),
|
||||
reduce_max(abs(per_channel[1].yzw)),
|
||||
reduce_max(abs(per_channel[2].yzw)));
|
||||
/* Find maximum of the sh function over all chanels. */
|
||||
vec3 max_sh = abs(sh.L0.M0.rgb) * 0.282094792 + max_L1 * 0.488602512;
|
||||
|
||||
float fac = clamp_value * safe_rcp(reduce_max(max_sh));
|
||||
if (fac > 1.0) {
|
||||
return sh;
|
||||
}
|
||||
return spherical_harmonics_mul(sh, fac);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
|
||||
#ifdef VOLUME_LIGHTING
|
||||
|
||||
vec3 volume_scatter_light_eval(
|
||||
const bool is_directional, vec3 P, vec3 V, uint l_idx, float s_anisotropy)
|
||||
vec3 volume_light_eval(const bool is_directional, vec3 P, vec3 V, uint l_idx, float s_anisotropy)
|
||||
{
|
||||
LightData light = light_buf[l_idx];
|
||||
|
||||
|
@ -48,10 +47,24 @@ vec3 volume_scatter_light_eval(
|
|||
return vec3(0);
|
||||
}
|
||||
|
||||
vec3 Li = volume_light(light, is_directional, lv) * visibility *
|
||||
volume_shadow(light, is_directional, P, lv, extinction_tx);
|
||||
vec3 Li = volume_light(light, is_directional, lv) * visibility;
|
||||
|
||||
return colorspace_brightness_clamp_max(Li, uniform_buf.volumes.light_clamp);
|
||||
if (light.tilemap_index != LIGHT_NO_SHADOW) {
|
||||
Li *= volume_shadow(light, is_directional, P, lv, extinction_tx);
|
||||
}
|
||||
|
||||
return Li;
|
||||
}
|
||||
|
||||
vec3 volume_lightprobe_eval(vec3 P, vec3 V, float s_anisotropy)
|
||||
{
|
||||
SphericalHarmonicL1 phase_sh = volume_phase_function_as_sh_L1(V, s_anisotropy);
|
||||
SphericalHarmonicL1 volume_radiance_sh = lightprobe_irradiance_sample(P);
|
||||
|
||||
float clamp_indirect = uniform_buf.clamp.volume_indirect;
|
||||
volume_radiance_sh = spherical_harmonics_clamp(volume_radiance_sh, clamp_indirect);
|
||||
|
||||
return spherical_harmonics_dot(volume_radiance_sh, phase_sh).xyz;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -81,25 +94,35 @@ void main()
|
|||
float s_anisotropy = phase.x / max(1.0, phase.y);
|
||||
|
||||
#ifdef VOLUME_LIGHTING
|
||||
SphericalHarmonicL1 phase_sh = volume_phase_function_as_sh_L1(V, s_anisotropy);
|
||||
SphericalHarmonicL1 volume_radiance_sh = lightprobe_irradiance_sample(P);
|
||||
vec3 direct_radiance = vec3(0.0);
|
||||
|
||||
vec3 light_scattering = spherical_harmonics_dot(volume_radiance_sh, phase_sh).xyz;
|
||||
if (reduce_max(s_scattering) > 0.0) {
|
||||
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
|
||||
direct_radiance += volume_light_eval(true, P, V, l_idx, s_anisotropy);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
|
||||
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
|
||||
light_scattering += volume_scatter_light_eval(true, P, V, l_idx, s_anisotropy);
|
||||
vec2 pixel = ((vec2(froxel.xy) + 0.5) * uniform_buf.volumes.inv_tex_size.xy) *
|
||||
uniform_buf.volumes.main_view_extent;
|
||||
|
||||
LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx)
|
||||
{
|
||||
direct_radiance += volume_light_eval(false, P, V, l_idx, s_anisotropy);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
|
||||
vec2 pixel = ((vec2(froxel.xy) + 0.5) * uniform_buf.volumes.inv_tex_size.xy) *
|
||||
uniform_buf.volumes.main_view_extent;
|
||||
vec3 indirect_radiance = volume_lightprobe_eval(P, V, s_anisotropy).xyz;
|
||||
|
||||
LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) {
|
||||
light_scattering += volume_scatter_light_eval(false, P, V, l_idx, s_anisotropy);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
direct_radiance *= s_scattering;
|
||||
indirect_radiance *= s_scattering;
|
||||
|
||||
scattering += light_scattering * s_scattering;
|
||||
float clamp_direct = uniform_buf.clamp.volume_direct;
|
||||
float clamp_indirect = uniform_buf.clamp.volume_indirect;
|
||||
direct_radiance = colorspace_brightness_clamp_max(direct_radiance, clamp_direct);
|
||||
indirect_radiance = colorspace_brightness_clamp_max(indirect_radiance, clamp_indirect);
|
||||
|
||||
scattering += direct_radiance + indirect_radiance;
|
||||
#endif
|
||||
|
||||
if (uniform_buf.volumes.history_opacity > 0.0) {
|
||||
|
|
|
@ -61,6 +61,11 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light)
|
|||
.image_out(2, DEFERRED_RADIANCE_FORMAT, "direct_radiance_1_img")
|
||||
.image_out(3, DEFERRED_RADIANCE_FORMAT, "direct_radiance_2_img")
|
||||
.image_out(4, DEFERRED_RADIANCE_FORMAT, "direct_radiance_3_img")
|
||||
/* Optimized out if use_split_indirect is false. */
|
||||
.image_out(5, DEFERRED_RADIANCE_FORMAT, "indirect_radiance_1_img")
|
||||
.image_out(6, DEFERRED_RADIANCE_FORMAT, "indirect_radiance_2_img")
|
||||
.image_out(7, DEFERRED_RADIANCE_FORMAT, "indirect_radiance_3_img")
|
||||
.specialization_constant(Type::BOOL, "use_split_indirect", false)
|
||||
.specialization_constant(Type::BOOL, "use_lightprobe_eval", false)
|
||||
.specialization_constant(Type::BOOL, "render_pass_shadow_enabled", true)
|
||||
.define("SPECIALIZED_SHADOW_PARAMS")
|
||||
|
@ -103,6 +108,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_combine)
|
|||
.sampler(5, ImageType::FLOAT_2D, "indirect_radiance_1_tx")
|
||||
.sampler(6, ImageType::FLOAT_2D, "indirect_radiance_2_tx")
|
||||
.sampler(7, ImageType::FLOAT_2D, "indirect_radiance_3_tx")
|
||||
.image(5, GPU_RGBA16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "radiance_feedback_img")
|
||||
.fragment_out(0, Type::VEC4, "out_combined")
|
||||
.additional_info("eevee_shared",
|
||||
"eevee_gbuffer_data",
|
||||
|
@ -114,7 +120,8 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_combine)
|
|||
.specialization_constant(Type::BOOL, "render_pass_diffuse_light_enabled", true)
|
||||
.specialization_constant(Type::BOOL, "render_pass_specular_light_enabled", true)
|
||||
.specialization_constant(Type::BOOL, "render_pass_normal_enabled", true)
|
||||
.specialization_constant(Type::BOOL, "use_combined_lightprobe_eval", false)
|
||||
.specialization_constant(Type::BOOL, "use_radiance_feedback", false)
|
||||
.specialization_constant(Type::BOOL, "use_split_radiance", false)
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_deferred_capture_eval)
|
||||
|
|
|
@ -174,7 +174,7 @@ GPU_SHADER_CREATE_INFO(eevee_lightprobe_irradiance_world)
|
|||
IRRADIANCE_GRID_BRICK_SIZE,
|
||||
IRRADIANCE_GRID_BRICK_SIZE)
|
||||
.define("IRRADIANCE_GRID_UPLOAD")
|
||||
.additional_info("eevee_shared")
|
||||
.additional_info("eevee_shared", "eevee_global_ubo")
|
||||
.push_constant(Type::INT, "grid_index")
|
||||
.storage_buf(0, Qualifier::READ, "uint", "bricks_infos_buf[]")
|
||||
.storage_buf(1, Qualifier::READ, "SphereProbeHarmonic", "harmonic_buf")
|
||||
|
@ -188,7 +188,7 @@ GPU_SHADER_CREATE_INFO(eevee_lightprobe_irradiance_load)
|
|||
IRRADIANCE_GRID_BRICK_SIZE,
|
||||
IRRADIANCE_GRID_BRICK_SIZE)
|
||||
.define("IRRADIANCE_GRID_UPLOAD")
|
||||
.additional_info("eevee_shared")
|
||||
.additional_info("eevee_shared", "eevee_global_ubo")
|
||||
.push_constant(Type::MAT4, "grid_local_to_world")
|
||||
.push_constant(Type::INT, "grid_index")
|
||||
.push_constant(Type::INT, "grid_start_index")
|
||||
|
|
|
@ -23,13 +23,12 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_remap)
|
|||
.push_constant(Type::IVEC4, "probe_coord_packed")
|
||||
.push_constant(Type::IVEC4, "write_coord_packed")
|
||||
.push_constant(Type::IVEC4, "world_coord_packed")
|
||||
.push_constant(Type::FLOAT, "probe_brightness_clamp")
|
||||
.sampler(0, ImageType::FLOAT_CUBE, "cubemap_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D_ARRAY, "atlas_tx")
|
||||
.storage_buf(0, Qualifier::WRITE, "SphereProbeHarmonic", "out_sh[SPHERE_PROBE_MAX_HARMONIC]")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "atlas_img")
|
||||
.compute_source("eevee_reflection_probe_remap_comp.glsl")
|
||||
.additional_info("eevee_shared")
|
||||
.additional_info("eevee_shared", "eevee_global_ubo")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_reflection_probe_irradiance)
|
||||
|
@ -48,7 +47,10 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_select)
|
|||
"SphereProbeData",
|
||||
"reflection_probe_buf[SPHERE_PROBE_MAX]")
|
||||
.push_constant(Type::INT, "reflection_probe_count")
|
||||
.additional_info("eevee_shared", "eevee_sampling_data", "eevee_volume_probe_data")
|
||||
.additional_info("eevee_shared",
|
||||
"eevee_sampling_data",
|
||||
"eevee_global_ubo",
|
||||
"eevee_volume_probe_data")
|
||||
.compute_source("eevee_reflection_probe_select_comp.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
|
|
|
@ -61,11 +61,12 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_update)
|
|||
GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_opaque)
|
||||
.do_static_compilation(true)
|
||||
.local_group_size(SHADOW_DEPTH_SCAN_GROUP_SIZE, SHADOW_DEPTH_SCAN_GROUP_SIZE)
|
||||
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
|
||||
.storage_buf(5, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
|
||||
.storage_buf(6, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
|
||||
.push_constant(Type::IVEC2, "input_depth_extent")
|
||||
.push_constant(Type::FLOAT, "tilemap_proj_ratio")
|
||||
.additional_info("eevee_shared", "draw_view", "draw_view_culling", "eevee_light_data")
|
||||
.additional_info(
|
||||
"eevee_shared", "draw_view", "draw_view_culling", "eevee_hiz_data", "eevee_light_data")
|
||||
.compute_source("eevee_shadow_tag_usage_comp.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_surfels)
|
||||
|
|
|
@ -55,6 +55,7 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata)
|
|||
sh = OVERLAY_shader_edit_particle_point();
|
||||
grp = pd->edit_curves_points_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_points_ps[i]);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "useWeight", false);
|
||||
}
|
||||
DRW_PASS_CREATE(psl->edit_curves_lines_ps[i], (state | pd->clipping_state));
|
||||
sh = OVERLAY_shader_edit_particle_strand();
|
||||
|
|
|
@ -184,6 +184,7 @@ static void OVERLAY_cache_init(void *vedata)
|
|||
case CTX_MODE_PAINT_GREASE_PENCIL:
|
||||
case CTX_MODE_SCULPT_GREASE_PENCIL:
|
||||
case CTX_MODE_EDIT_GREASE_PENCIL:
|
||||
case CTX_MODE_WEIGHT_GREASE_PENCIL:
|
||||
OVERLAY_edit_grease_pencil_cache_init(data);
|
||||
break;
|
||||
case CTX_MODE_PARTICLE:
|
||||
|
@ -294,6 +295,14 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool overlay_object_is_paint_mode(const DRWContextState *draw_ctx, const Object *ob)
|
||||
{
|
||||
if (ob->type == OB_GREASE_PENCIL && draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) {
|
||||
return true;
|
||||
}
|
||||
return (ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT);
|
||||
}
|
||||
|
||||
static bool overlay_should_fade_object(Object *ob, Object *active_object)
|
||||
{
|
||||
if (!active_object || !ob) {
|
||||
|
@ -336,8 +345,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
|
|||
false;
|
||||
const bool in_particle_edit_mode = (ob->mode == OB_MODE_PARTICLE_EDIT) &&
|
||||
(pd->ctx_mode == CTX_MODE_PARTICLE);
|
||||
const bool in_paint_mode = (ob == draw_ctx->obact) &&
|
||||
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
|
||||
const bool in_paint_mode = overlay_object_is_paint_mode(draw_ctx, ob);
|
||||
const bool in_sculpt_curve_mode = (ob == draw_ctx->obact ||
|
||||
(is_preview && dupli_parent == draw_ctx->obact &&
|
||||
ob->type == OB_CURVES)) &&
|
||||
|
@ -464,6 +472,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
|
|||
case OB_MODE_TEXTURE_PAINT:
|
||||
OVERLAY_paint_texture_cache_populate(data, ob);
|
||||
break;
|
||||
case OB_MODE_WEIGHT_GPENCIL_LEGACY:
|
||||
OVERLAY_weight_grease_pencil_cache_populate(data, ob);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -750,6 +761,7 @@ static void OVERLAY_draw_scene(void *vedata)
|
|||
OVERLAY_edit_curves_draw(data);
|
||||
break;
|
||||
case CTX_MODE_EDIT_GREASE_PENCIL:
|
||||
case CTX_MODE_WEIGHT_GREASE_PENCIL:
|
||||
OVERLAY_edit_grease_pencil_draw(data);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -20,7 +20,7 @@ void OVERLAY_facing_cache_init(OVERLAY_Data *vedata)
|
|||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
/* Non Meshes Pass (Camera, empties, lights ...) */
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->facing_ps[i], state | pd->clipping_state);
|
||||
|
||||
GPUShader *sh = OVERLAY_shader_facing();
|
||||
|
|
|
@ -23,7 +23,7 @@ void OVERLAY_fade_cache_init(OVERLAY_Data *vedata)
|
|||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
/* Non Meshes Pass (Camera, empties, lights ...) */
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->fade_ps[i], state | pd->clipping_state);
|
||||
|
||||
GPUShader *sh = OVERLAY_shader_uniform_color();
|
||||
|
|
|
@ -24,6 +24,7 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
|
|||
const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(
|
||||
draw_ctx->scene->toolsettings);
|
||||
const View3D *v3d = draw_ctx->v3d;
|
||||
const bool use_weight = (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) != 0;
|
||||
|
||||
GPUShader *sh;
|
||||
DRWShadingGroup *grp;
|
||||
|
@ -32,19 +33,23 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
|
|||
DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->edit_grease_pencil_ps, (state | pd->clipping_state));
|
||||
|
||||
const bool show_points = selection_domain == bke::AttrDomain::Point;
|
||||
const bool show_points = (selection_domain == bke::AttrDomain::Point) || use_weight;
|
||||
const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) != 0;
|
||||
|
||||
if (show_lines) {
|
||||
sh = OVERLAY_shader_edit_particle_strand();
|
||||
grp = pd->edit_grease_pencil_wires_grp = DRW_shgroup_create(sh, psl->edit_grease_pencil_ps);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "useWeight", use_weight);
|
||||
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
|
||||
}
|
||||
|
||||
if (show_points) {
|
||||
sh = OVERLAY_shader_edit_particle_point();
|
||||
grp = pd->edit_grease_pencil_points_grp = DRW_shgroup_create(sh, psl->edit_grease_pencil_ps);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "useWeight", use_weight);
|
||||
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +74,28 @@ void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
}
|
||||
}
|
||||
|
||||
void OVERLAY_weight_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
OVERLAY_PrivateData *pd = vedata->stl->pd;
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
|
||||
DRWShadingGroup *lines_grp = pd->edit_grease_pencil_wires_grp;
|
||||
if (lines_grp) {
|
||||
blender::gpu::Batch *geom_lines = DRW_cache_grease_pencil_weight_lines_get(draw_ctx->scene,
|
||||
ob);
|
||||
|
||||
DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
|
||||
}
|
||||
|
||||
DRWShadingGroup *points_grp = pd->edit_grease_pencil_points_grp;
|
||||
if (points_grp) {
|
||||
blender::gpu::Batch *geom_points = DRW_cache_grease_pencil_weight_points_get(draw_ctx->scene,
|
||||
ob);
|
||||
DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
|
||||
}
|
||||
}
|
||||
|
||||
void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata)
|
||||
{
|
||||
OVERLAY_PassList *psl = vedata->psl;
|
||||
|
|
|
@ -249,16 +249,7 @@ void OVERLAY_paint_vertex_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
|
||||
void OVERLAY_paint_weight_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
OVERLAY_paint_vertex_cache_populate(vedata, ob);
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
/* TODO */
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
OVERLAY_paint_vertex_cache_populate(vedata, ob);
|
||||
}
|
||||
|
||||
void OVERLAY_paint_draw(OVERLAY_Data *vedata)
|
||||
|
|
|
@ -46,6 +46,7 @@ void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata)
|
|||
sh = OVERLAY_shader_edit_particle_point();
|
||||
pd->edit_particle_point_grp = grp = DRW_shgroup_create(sh, psl->edit_particle_ps);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "useWeight", false);
|
||||
}
|
||||
|
||||
void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
|
|
|
@ -564,6 +564,7 @@ void OVERLAY_edit_gpencil_legacy_draw(OVERLAY_Data *vedata);
|
|||
|
||||
void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata);
|
||||
void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
|
||||
void OVERLAY_weight_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
|
||||
void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata);
|
||||
|
||||
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata);
|
||||
|
|
|
@ -571,6 +571,8 @@ GPU_SHADER_CREATE_INFO(overlay_edit_particle_point)
|
|||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::FLOAT, "selection")
|
||||
.vertex_out(overlay_edit_flat_color_iface)
|
||||
.sampler(0, ImageType::FLOAT_1D, "weightTex")
|
||||
.push_constant(Type::BOOL, "useWeight")
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.vertex_source("overlay_edit_particle_point_vert.glsl")
|
||||
.fragment_source("overlay_point_varying_color_frag.glsl")
|
||||
|
|
|
@ -5,12 +5,34 @@
|
|||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
#define no_active_weight 666.0
|
||||
|
||||
vec3 weight_to_rgb(float t)
|
||||
{
|
||||
if (t == no_active_weight) {
|
||||
/* No weight. */
|
||||
return colorWire.rgb;
|
||||
}
|
||||
if (t > 1.0 || t < 0.0) {
|
||||
/* Error color */
|
||||
return vec3(1.0, 0.0, 1.0);
|
||||
}
|
||||
else {
|
||||
return texture(weightTex, t).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
|
||||
finalColor = mix(colorWire, colorVertexSelect, selection);
|
||||
if (useWeight) {
|
||||
finalColor = vec4(weight_to_rgb(selection), 1.0);
|
||||
}
|
||||
else {
|
||||
finalColor = mix(colorWire, colorVertexSelect, selection);
|
||||
}
|
||||
|
||||
gl_PointSize = sizeVertex * 2.0;
|
||||
|
||||
|
|
|
@ -286,4 +286,6 @@ blender::gpu::Batch *DRW_cache_grease_pencil_edit_points_get(const Scene *scene,
|
|||
blender::gpu::Batch *DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *ob);
|
||||
gpu::VertBuf *DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Object *ob);
|
||||
gpu::VertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object *ob);
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -310,7 +310,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
Mesh *mesh,
|
||||
bool is_editmode,
|
||||
bool is_paint_mode,
|
||||
bool is_mode_active,
|
||||
bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
bool do_final,
|
||||
bool do_uvedit,
|
||||
|
|
|
@ -571,7 +571,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
|
@ -698,7 +698,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
mesh,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
object_to_world,
|
||||
do_final,
|
||||
do_uvedit,
|
||||
|
|
|
@ -576,7 +576,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
Mesh *mesh,
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
|
@ -599,7 +599,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
mr->bm = mesh->runtime->edit_mesh->bm;
|
||||
mr->edit_bmesh = mesh->runtime->edit_mesh.get();
|
||||
mr->mesh = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
|
||||
mr->edit_data = is_mode_active ? mr->mesh->runtime->edit_data.get() : nullptr;
|
||||
mr->edit_data = edit_mode_active ? mr->mesh->runtime->edit_data.get() : nullptr;
|
||||
|
||||
/* If there is no distinct cage, hide unmapped edges that can't be selected. */
|
||||
mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage;
|
||||
|
@ -636,7 +636,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
/* Use bmesh directly when the object is in edit mode unchanged by any modifiers.
|
||||
* For non-final UVs, always use original bmesh since the UV editor does not support
|
||||
* using the cage mesh with deformed coordinates. */
|
||||
if ((is_mode_active && mr->mesh->runtime->is_original_bmesh &&
|
||||
if ((edit_mode_active && mr->mesh->runtime->is_original_bmesh &&
|
||||
mr->mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) ||
|
||||
(do_uvedit && !do_final))
|
||||
{
|
||||
|
@ -646,7 +646,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
mr->extract_type = MR_EXTRACT_MESH;
|
||||
|
||||
/* Use mapping from final to original mesh when the object is in edit mode. */
|
||||
if (is_mode_active && do_final) {
|
||||
if (edit_mode_active && do_final) {
|
||||
mr->v_origindex = static_cast<const int *>(
|
||||
CustomData_get_layer(&mr->mesh->vert_data, CD_ORIGINDEX));
|
||||
mr->e_origindex = static_cast<const int *>(
|
||||
|
@ -709,7 +709,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
|
||||
mr->material_indices = *attributes.lookup<int>("material_index", bke::AttrDomain::Face);
|
||||
|
||||
if (is_mode_active || is_paint_mode) {
|
||||
if (edit_mode_active || is_paint_mode) {
|
||||
if (use_hide) {
|
||||
mr->hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
|
||||
mr->hide_edge = *attributes.lookup<bool>(".hide_edge", bke::AttrDomain::Edge);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_grease_pencil.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
|
||||
|
@ -209,6 +210,189 @@ static void copy_transformed_positions(const Span<float3> src_positions,
|
|||
}
|
||||
}
|
||||
|
||||
static void grease_pencil_weight_batch_ensure(Object &object,
|
||||
const GreasePencil &grease_pencil,
|
||||
const Scene &scene)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
|
||||
constexpr float no_active_weight = 666.0f;
|
||||
|
||||
BLI_assert(grease_pencil.runtime != nullptr);
|
||||
GreasePencilBatchCache *cache = static_cast<GreasePencilBatchCache *>(
|
||||
grease_pencil.runtime->batch_cache);
|
||||
|
||||
if (cache->edit_points_pos != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Should be discarded together. */
|
||||
BLI_assert(cache->edit_points_pos == nullptr && cache->edit_line_indices == nullptr &&
|
||||
cache->edit_points_indices == nullptr);
|
||||
BLI_assert(cache->edit_points == nullptr && cache->edit_lines == nullptr);
|
||||
|
||||
/* Get active vertex group. */
|
||||
const bDeformGroup *active_defgroup = static_cast<bDeformGroup *>(BLI_findlink(
|
||||
&grease_pencil.vertex_group_names, grease_pencil.vertex_group_active_index - 1));
|
||||
const char *active_defgroup_name = (active_defgroup == nullptr) ? "" : active_defgroup->name;
|
||||
|
||||
/* Get the visible drawings. */
|
||||
const Vector<ed::greasepencil::DrawingInfo> drawings =
|
||||
ed::greasepencil::retrieve_visible_drawings(scene, grease_pencil, false);
|
||||
|
||||
const Span<const Layer *> layers = grease_pencil.layers();
|
||||
|
||||
static GPUVertFormat format_points_pos = {0};
|
||||
if (format_points_pos.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format_points_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
static GPUVertFormat format_points_weight = {0};
|
||||
if (format_points_weight.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format_points_weight, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
|
||||
cache->edit_points_pos = GPU_vertbuf_create_with_format_ex(&format_points_pos, vbo_flag);
|
||||
cache->edit_points_selection = GPU_vertbuf_create_with_format_ex(&format_points_weight,
|
||||
vbo_flag);
|
||||
|
||||
int visible_points_num = 0;
|
||||
int total_line_ids_num = 0;
|
||||
int total_points_num = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
total_points_num += curves.points_num();
|
||||
}
|
||||
|
||||
GPU_vertbuf_data_alloc(cache->edit_points_pos, total_points_num);
|
||||
GPU_vertbuf_data_alloc(cache->edit_points_selection, total_points_num);
|
||||
|
||||
MutableSpan<float3> points_pos = {
|
||||
static_cast<float3 *>(GPU_vertbuf_get_data(cache->edit_points_pos)),
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos)};
|
||||
MutableSpan<float> points_weight = {
|
||||
static_cast<float *>(GPU_vertbuf_get_data(cache->edit_points_selection)),
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_selection)};
|
||||
|
||||
int drawing_start_offset = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const Layer &layer = *layers[info.layer_index];
|
||||
const float4x4 layer_space_to_object_space = layer.to_object_space(object);
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||
object, info.drawing, memory);
|
||||
|
||||
const IndexRange points(drawing_start_offset, curves.points_num());
|
||||
const Span<float3> positions = curves.positions();
|
||||
MutableSpan<float3> positions_slice = points_pos.slice(points);
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange range) {
|
||||
copy_transformed_positions(positions, range, layer_space_to_object_space, positions_slice);
|
||||
});
|
||||
|
||||
/* Get vertex weights of the active vertex group in this drawing. */
|
||||
const VArray<float> weights = *curves.attributes().lookup_or_default<float>(
|
||||
active_defgroup_name, bke::AttrDomain::Point, no_active_weight);
|
||||
MutableSpan<float> weights_slice = points_weight.slice(points);
|
||||
weights.materialize(weights_slice);
|
||||
|
||||
drawing_start_offset += curves.points_num();
|
||||
|
||||
/* Add one id for the restart after every curve. */
|
||||
total_line_ids_num += visible_strokes.size();
|
||||
Array<int> size_per_editable_stroke(visible_strokes.size());
|
||||
offset_indices::gather_group_sizes(points_by_curve, visible_strokes, size_per_editable_stroke);
|
||||
/* Add one id for every non-cyclic segment. */
|
||||
total_line_ids_num += std::accumulate(
|
||||
size_per_editable_stroke.begin(), size_per_editable_stroke.end(), 0);
|
||||
/* Add one id for the last segment of every cyclic curve. */
|
||||
total_line_ids_num += array_utils::count_booleans(curves.cyclic(), visible_strokes);
|
||||
|
||||
/* Do not show weights for locked layers. */
|
||||
if (layer.is_locked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visible_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
visible_points_num += points.size();
|
||||
});
|
||||
}
|
||||
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init_ex(&elb,
|
||||
GPU_PRIM_LINE_STRIP,
|
||||
total_line_ids_num,
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos));
|
||||
|
||||
GPUIndexBufBuilder epb;
|
||||
GPU_indexbuf_init_ex(&epb,
|
||||
GPU_PRIM_POINTS,
|
||||
visible_points_num,
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos));
|
||||
|
||||
/* Fill point index buffer with data. */
|
||||
drawing_start_offset = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const Layer *layer = layers[info.layer_index];
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||
object, info.drawing, memory);
|
||||
|
||||
/* Fill line indices. */
|
||||
visible_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const bool is_cyclic = cyclic[curve_i];
|
||||
|
||||
for (const int point_i : points) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, point_i + drawing_start_offset);
|
||||
}
|
||||
|
||||
if (is_cyclic) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset);
|
||||
}
|
||||
|
||||
GPU_indexbuf_add_primitive_restart(&elb);
|
||||
});
|
||||
|
||||
/* Fill point indices. */
|
||||
if (!layer->is_locked()) {
|
||||
visible_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
for (const int point : points) {
|
||||
GPU_indexbuf_add_generic_vert(&epb, point + drawing_start_offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
drawing_start_offset += curves.points_num();
|
||||
}
|
||||
|
||||
cache->edit_line_indices = GPU_indexbuf_build(&elb);
|
||||
cache->edit_points_indices = GPU_indexbuf_build(&epb);
|
||||
|
||||
/* Create the batches. */
|
||||
cache->edit_points = GPU_batch_create(
|
||||
GPU_PRIM_POINTS, cache->edit_points_pos, cache->edit_points_indices);
|
||||
GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_selection, false);
|
||||
|
||||
cache->edit_lines = GPU_batch_create(
|
||||
GPU_PRIM_LINE_STRIP, cache->edit_points_pos, cache->edit_line_indices);
|
||||
GPU_batch_vertbuf_add(cache->edit_lines, cache->edit_points_selection, false);
|
||||
|
||||
/* Allow creation of buffer texture. */
|
||||
GPU_vertbuf_use(cache->edit_points_pos);
|
||||
GPU_vertbuf_use(cache->edit_points_selection);
|
||||
|
||||
cache->is_dirty = false;
|
||||
}
|
||||
|
||||
static void grease_pencil_edit_batch_ensure(Object &object,
|
||||
const GreasePencil &grease_pencil,
|
||||
const Scene &scene)
|
||||
|
@ -752,4 +936,22 @@ gpu::VertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Objec
|
|||
return cache->vbo_col;
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob)
|
||||
{
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
|
||||
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
|
||||
grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene);
|
||||
|
||||
return cache->edit_points;
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object *ob)
|
||||
{
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
|
||||
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
|
||||
grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene);
|
||||
|
||||
return cache->edit_lines;
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -1383,7 +1383,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
DRW_object_is_in_edit_mode(ob);
|
||||
|
||||
/* This could be set for paint mode too, currently it's only used for edit-mode. */
|
||||
const bool is_mode_active = is_editmode && DRW_object_is_in_edit_mode(ob);
|
||||
const bool edit_mode_active = is_editmode && DRW_object_is_in_edit_mode(ob);
|
||||
|
||||
DRWBatchFlag batch_requested = cache.batch_requested;
|
||||
cache.batch_requested = (DRWBatchFlag)0;
|
||||
|
@ -1512,7 +1512,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
cache.batch_ready |= batch_requested;
|
||||
|
||||
bool do_cage = false, do_uvcage = false;
|
||||
if (is_editmode && is_mode_active) {
|
||||
if (is_editmode && edit_mode_active) {
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
|
||||
|
@ -1871,7 +1871,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
mesh,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
ob->object_to_world(),
|
||||
false,
|
||||
true,
|
||||
|
@ -1888,7 +1888,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
mesh,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
ob->object_to_world(),
|
||||
false,
|
||||
false,
|
||||
|
@ -1904,7 +1904,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
&cache.final,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
ob->object_to_world(),
|
||||
true,
|
||||
false,
|
||||
|
@ -1925,7 +1925,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
mesh,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
ob->object_to_world(),
|
||||
true,
|
||||
false,
|
||||
|
|
|
@ -2094,7 +2094,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
|
|||
MeshBufferCache &mbc,
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
|
@ -2172,7 +2172,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
|
|||
mesh,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
object_to_world,
|
||||
do_final,
|
||||
do_uvedit,
|
||||
|
@ -2319,7 +2319,7 @@ void DRW_create_subdivision(Object *ob,
|
|||
MeshBufferCache *mbc,
|
||||
const bool is_editmode,
|
||||
const bool is_paint_mode,
|
||||
const bool is_mode_active,
|
||||
const bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
const bool do_final,
|
||||
const bool do_uvedit,
|
||||
|
@ -2343,7 +2343,7 @@ void DRW_create_subdivision(Object *ob,
|
|||
*mbc,
|
||||
is_editmode,
|
||||
is_paint_mode,
|
||||
is_mode_active,
|
||||
edit_mode_active,
|
||||
object_to_world,
|
||||
do_final,
|
||||
do_uvedit,
|
||||
|
|
|
@ -203,7 +203,7 @@ void DRW_create_subdivision(Object *ob,
|
|||
MeshBufferCache *mbc,
|
||||
bool is_editmode,
|
||||
bool is_paint_mode,
|
||||
bool is_mode_active,
|
||||
bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
bool do_final,
|
||||
bool do_uvedit,
|
||||
|
|
|
@ -228,16 +228,6 @@ void View::frustum_culling_sphere_calc(int view_id)
|
|||
}
|
||||
}
|
||||
|
||||
void View::disable(IndexRange range)
|
||||
{
|
||||
/* Set bounding sphere to -1.0f radius will bypass the culling test and treat every instance as
|
||||
* invisible. */
|
||||
range = IndexRange(view_len_).intersect(range);
|
||||
for (auto view_id : range) {
|
||||
reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere)->radius = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void View::bind()
|
||||
{
|
||||
if (dirty_ && !procedural_) {
|
||||
|
|
|
@ -73,9 +73,6 @@ class View {
|
|||
/* For compatibility with old system. Will be removed at some point. */
|
||||
void sync(const DRWView *view);
|
||||
|
||||
/** Disable a range in the multi-view array. Disabled view will not produce any instances. */
|
||||
void disable(IndexRange range);
|
||||
|
||||
/** Enable or disable every visibility test (frustum culling, HiZ culling). */
|
||||
void visibility_test(bool enable)
|
||||
{
|
||||
|
|
|
@ -278,14 +278,14 @@ struct MeshExtract {
|
|||
/* `draw_cache_extract_mesh_render_data.cc` */
|
||||
|
||||
/**
|
||||
* \param is_mode_active: When true, use the modifiers from the edit-data,
|
||||
* \param edit_mode_active: When true, use the modifiers from the edit-data,
|
||||
* otherwise don't use modifiers as they are not from this object.
|
||||
*/
|
||||
MeshRenderData *mesh_render_data_create(Object *object,
|
||||
Mesh *mesh,
|
||||
bool is_editmode,
|
||||
bool is_paint_mode,
|
||||
bool is_mode_active,
|
||||
bool edit_mode_active,
|
||||
const float4x4 &object_to_world,
|
||||
bool do_final,
|
||||
bool do_uvedit,
|
||||
|
|
|
@ -962,6 +962,7 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
|
|||
|
||||
static int insert_key_button_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
using namespace blender::animrig;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
@ -992,15 +993,14 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
|
|||
FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
|
||||
|
||||
if (fcu) {
|
||||
changed = blender::animrig::insert_keyframe_direct(
|
||||
op->reports,
|
||||
ptr,
|
||||
prop,
|
||||
fcu,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
nullptr,
|
||||
eInsertKeyFlags(0));
|
||||
changed = insert_keyframe_direct(op->reports,
|
||||
ptr,
|
||||
prop,
|
||||
fcu,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
nullptr,
|
||||
eInsertKeyFlags(0));
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports,
|
||||
|
@ -1017,19 +1017,18 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
|
|||
C, &ptr, prop, index, nullptr, nullptr, &driven, &special);
|
||||
|
||||
if (fcu && driven) {
|
||||
const float driver_frame = blender::animrig::evaluate_driver_from_rna_pointer(
|
||||
const float driver_frame = evaluate_driver_from_rna_pointer(
|
||||
&anim_eval_context, &ptr, prop, fcu);
|
||||
AnimationEvalContext remapped_context = BKE_animsys_eval_context_construct(
|
||||
CTX_data_depsgraph_pointer(C), driver_frame);
|
||||
changed = blender::animrig::insert_keyframe_direct(
|
||||
op->reports,
|
||||
ptr,
|
||||
prop,
|
||||
fcu,
|
||||
&remapped_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
nullptr,
|
||||
INSERTKEY_NOFLAGS);
|
||||
changed = insert_keyframe_direct(op->reports,
|
||||
ptr,
|
||||
prop,
|
||||
fcu,
|
||||
&remapped_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
nullptr,
|
||||
INSERTKEY_NOFLAGS);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1064,15 +1063,15 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
|
|||
index = -1;
|
||||
}
|
||||
|
||||
changed = (blender::animrig::insert_keyframe(bmain,
|
||||
op->reports,
|
||||
ptr.owner_id,
|
||||
group,
|
||||
path->c_str(),
|
||||
index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag) != 0);
|
||||
CombinedKeyingResult result = insert_keyframe(bmain,
|
||||
*ptr.owner_id,
|
||||
group,
|
||||
path->c_str(),
|
||||
index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
changed = result.get_count(SingleKeyingResult::SUCCESS) != 0;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports,
|
||||
|
|
|
@ -1020,6 +1020,7 @@ static int insert_key_to_keying_set_path(bContext *C,
|
|||
const eModifyKey_Modes mode,
|
||||
const float frame)
|
||||
{
|
||||
using namespace blender::animrig;
|
||||
/* Since keying settings can be defined on the paths too,
|
||||
* apply the settings for this path first. */
|
||||
const eInsertKeyFlags path_insert_key_flags = keyingset_apply_keying_flags(
|
||||
|
@ -1074,29 +1075,36 @@ static int insert_key_to_keying_set_path(bContext *C,
|
|||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
||||
frame);
|
||||
int keyed_channels = 0;
|
||||
|
||||
CombinedKeyingResult combined_result;
|
||||
for (; array_index < array_length; array_index++) {
|
||||
if (mode == MODIFYKEY_MODE_INSERT) {
|
||||
keyed_channels += blender::animrig::insert_keyframe(bmain,
|
||||
reports,
|
||||
keyingset_path->id,
|
||||
groupname,
|
||||
keyingset_path->rna_path,
|
||||
array_index,
|
||||
&anim_eval_context,
|
||||
keytype,
|
||||
path_insert_key_flags);
|
||||
CombinedKeyingResult result = insert_keyframe(bmain,
|
||||
*keyingset_path->id,
|
||||
groupname,
|
||||
keyingset_path->rna_path,
|
||||
array_index,
|
||||
&anim_eval_context,
|
||||
keytype,
|
||||
path_insert_key_flags);
|
||||
keyed_channels += result.get_count(SingleKeyingResult::SUCCESS);
|
||||
combined_result.merge(result);
|
||||
}
|
||||
else if (mode == MODIFYKEY_MODE_DELETE) {
|
||||
keyed_channels += blender::animrig::delete_keyframe(bmain,
|
||||
reports,
|
||||
keyingset_path->id,
|
||||
nullptr,
|
||||
keyingset_path->rna_path,
|
||||
array_index,
|
||||
frame);
|
||||
keyed_channels += delete_keyframe(bmain,
|
||||
reports,
|
||||
keyingset_path->id,
|
||||
nullptr,
|
||||
keyingset_path->rna_path,
|
||||
array_index,
|
||||
frame);
|
||||
}
|
||||
}
|
||||
|
||||
if (combined_result.get_count(SingleKeyingResult::SUCCESS) == 0) {
|
||||
combined_result.generate_reports(reports);
|
||||
}
|
||||
|
||||
switch (GS(keyingset_path->id->name)) {
|
||||
case ID_OB: /* Object (or Object-Related) Keyframes */
|
||||
{
|
||||
|
|
|
@ -601,10 +601,10 @@ static bool gpencil_weightmode_toggle_poll(bContext *C)
|
|||
{
|
||||
/* if using gpencil object, use this gpd */
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if ((ob) && (ob->type == OB_GPENCIL_LEGACY)) {
|
||||
if ((ob) && (ELEM(ob->type, OB_GPENCIL_LEGACY, OB_GREASE_PENCIL))) {
|
||||
return ob->data != nullptr;
|
||||
}
|
||||
return ED_gpencil_data_get_active(C) != nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
|
||||
|
@ -615,36 +615,45 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
|
|||
const bool back = RNA_boolean_get(op->ptr, "back");
|
||||
|
||||
wmMsgBus *mbus = CTX_wm_message_bus(C);
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
bool is_object = false;
|
||||
short mode;
|
||||
/* if using a gpencil object, use this datablock */
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
const bool is_mode_set = (ob->mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) != 0;
|
||||
if ((ob) && (ob->type == OB_GPENCIL_LEGACY)) {
|
||||
gpd = static_cast<bGPdata *>(ob->data);
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
if (gpd == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
is_object = true;
|
||||
}
|
||||
const int mode_flag = OB_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
const bool is_mode_set = (ob->mode & mode_flag) != 0;
|
||||
|
||||
if (gpd == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
/* Just toggle weightmode flag... */
|
||||
gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
|
||||
/* set mode */
|
||||
if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
|
||||
mode = OB_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
}
|
||||
else {
|
||||
mode = OB_MODE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Just toggle weightmode flag... */
|
||||
gpd->flag ^= GP_DATA_STROKE_WEIGHTMODE;
|
||||
/* set mode */
|
||||
if (gpd->flag & GP_DATA_STROKE_WEIGHTMODE) {
|
||||
mode = OB_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
}
|
||||
else {
|
||||
mode = OB_MODE_OBJECT;
|
||||
else if ((ob) && (ob->type == OB_GREASE_PENCIL)) {
|
||||
is_object = true;
|
||||
if (!is_mode_set) {
|
||||
mode = OB_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
}
|
||||
else {
|
||||
mode = OB_MODE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_object) {
|
||||
/* try to back previous mode */
|
||||
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
|
||||
mode = ob->restore_mode;
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && (back == 1)) {
|
||||
mode = ob->restore_mode;
|
||||
}
|
||||
}
|
||||
ob->restore_mode = ob->mode;
|
||||
ob->mode = mode;
|
||||
|
@ -664,9 +673,16 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* setup other modes */
|
||||
ED_gpencil_setup_modes(C, gpd, mode);
|
||||
/* set cache as dirty */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
ED_gpencil_setup_modes(C, gpd, mode);
|
||||
/* set cache as dirty */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
else if (ob->type == OB_GREASE_PENCIL) {
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
|
||||
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, nullptr);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE, nullptr);
|
||||
|
|
|
@ -548,11 +548,9 @@ static void init_brush_icons()
|
|||
|
||||
# define INIT_BRUSH_ICON(icon_id, name) \
|
||||
{ \
|
||||
uchar *rect = (uchar *)datatoc_##name##_png; \
|
||||
const uchar *rect = (const uchar *)datatoc_##name##_png; \
|
||||
const int size = datatoc_##name##_png_size; \
|
||||
DrawInfo *di; \
|
||||
\
|
||||
di = def_internal_icon(nullptr, icon_id, 0, 0, w, ICON_TYPE_BUFFER, 0); \
|
||||
DrawInfo *di = def_internal_icon(nullptr, icon_id, 0, 0, w, ICON_TYPE_BUFFER, 0); \
|
||||
di->data.buffer.image->datatoc_rect = rect; \
|
||||
di->data.buffer.image->datatoc_size = size; \
|
||||
} \
|
||||
|
@ -1616,8 +1614,8 @@ PreviewImage *UI_icon_to_preview(int icon_id)
|
|||
}
|
||||
|
||||
if (di->type == ICON_TYPE_PREVIEW) {
|
||||
PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
|
||||
static_cast<PreviewImage *>(icon->obj);
|
||||
const PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
|
||||
static_cast<const PreviewImage *>(icon->obj);
|
||||
|
||||
if (prv) {
|
||||
return BKE_previewimg_copy(prv);
|
||||
|
@ -2483,7 +2481,7 @@ int UI_icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, const b
|
|||
return RNA_int_get(ptr, "icon");
|
||||
}
|
||||
else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
|
||||
DynamicPaintSurface *surface = static_cast<DynamicPaintSurface *>(ptr->data);
|
||||
const DynamicPaintSurface *surface = static_cast<const DynamicPaintSurface *>(ptr->data);
|
||||
|
||||
if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
|
||||
return ICON_SHADING_TEXTURE;
|
||||
|
|
|
@ -148,8 +148,8 @@ bool mode_compat_test(const Object *ob, eObjectMode mode)
|
|||
}
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_WEIGHT_PAINT |
|
||||
OB_MODE_SCULPT_GPENCIL_LEGACY))
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_SCULPT_GPENCIL_LEGACY |
|
||||
OB_MODE_WEIGHT_GPENCIL_LEGACY))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ void mode_exit_generic(Object *ob, const eObjectMode mode_flag)
|
|||
bool mode_toggle_poll_test(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if (ob == nullptr || !ELEM(ob->type, OB_MESH, OB_GREASE_PENCIL)) {
|
||||
if (ob == nullptr || ob->type != OB_MESH) {
|
||||
return false;
|
||||
}
|
||||
if (!ob->data || ID_IS_LINKED(ob->data)) {
|
||||
|
|
|
@ -1543,31 +1543,9 @@ static void wpaint_paint_leaves(bContext *C,
|
|||
/** \name Enter Weight Paint Mode
|
||||
* \{ */
|
||||
|
||||
static void grease_pencil_wpaintmode_enter(Main *bmain, Scene *scene, Object *ob)
|
||||
{
|
||||
const PaintMode paint_mode = PaintMode::Weight;
|
||||
Paint *weight_paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
||||
BKE_paint_ensure(bmain, scene->toolsettings, &weight_paint);
|
||||
|
||||
ob->mode |= OB_MODE_WEIGHT_PAINT;
|
||||
|
||||
/* Flush object mode. */
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_SYNC_TO_EVAL);
|
||||
}
|
||||
|
||||
void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
vwpaint::mode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT);
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
grease_pencil_wpaintmode_enter(bmain, scene, ob);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
vwpaint::mode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT);
|
||||
}
|
||||
void ED_object_wpaintmode_enter(bContext *C, Depsgraph *depsgraph)
|
||||
{
|
||||
|
@ -1584,18 +1562,7 @@ void ED_object_wpaintmode_enter(bContext *C, Depsgraph *depsgraph)
|
|||
|
||||
void ED_object_wpaintmode_exit_ex(Object *ob)
|
||||
{
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
vwpaint::mode_exit_generic(ob, OB_MODE_WEIGHT_PAINT);
|
||||
break;
|
||||
case OB_GREASE_PENCIL: {
|
||||
ob->mode &= ~OB_MODE_WEIGHT_PAINT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
vwpaint::mode_exit_generic(ob, OB_MODE_WEIGHT_PAINT);
|
||||
}
|
||||
void ED_object_wpaintmode_exit(bContext *C)
|
||||
{
|
||||
|
@ -1668,6 +1635,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
|
||||
if (is_mode_set) {
|
||||
ED_object_wpaintmode_exit_ex(ob);
|
||||
}
|
||||
|
@ -1683,15 +1652,12 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
|
|||
/* Prepare armature posemode. */
|
||||
blender::ed::object::posemode_set_for_weight_paint(C, bmain, ob, is_mode_set);
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
/* Weight-paint works by overriding colors in mesh,
|
||||
* so need to make sure we recalculate on enter and
|
||||
* exit (exit needs doing regardless because we
|
||||
* should re-deform).
|
||||
*/
|
||||
Mesh *mesh = BKE_mesh_from_object(ob);
|
||||
DEG_id_tag_update(&mesh->id, 0);
|
||||
}
|
||||
/* Weight-paint works by overriding colors in mesh,
|
||||
* so need to make sure we recalculate on enter and
|
||||
* exit (exit needs doing regardless because we
|
||||
* should re-deform).
|
||||
*/
|
||||
DEG_id_tag_update(&mesh->id, 0);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
|
||||
|
||||
|
|
|
@ -853,15 +853,17 @@ static void insert_fcurve_key(bAnimContext *ac,
|
|||
* (TODO: add the full-blown PointerRNA relative parsing case here...)
|
||||
*/
|
||||
if (ale->id && !ale->owner) {
|
||||
insert_keyframe(ac->bmain,
|
||||
reports,
|
||||
ale->id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
CombinedKeyingResult result = insert_keyframe(ac->bmain,
|
||||
*ale->id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
if (result.get_count(SingleKeyingResult::SUCCESS) == 0) {
|
||||
result.generate_reports(reports);
|
||||
}
|
||||
}
|
||||
else {
|
||||
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
|
||||
|
|
|
@ -206,15 +206,17 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
|
|||
* up adding the keyframes on a new F-Curve in the action data instead.
|
||||
*/
|
||||
if (ale->id && !ale->owner && !fcu->driver) {
|
||||
insert_keyframe(ac->bmain,
|
||||
reports,
|
||||
ale->id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
CombinedKeyingResult result = insert_keyframe(ac->bmain,
|
||||
*ale->id,
|
||||
((fcu->grp) ? (fcu->grp->name) : (nullptr)),
|
||||
fcu->rna_path,
|
||||
fcu->array_index,
|
||||
&anim_eval_context,
|
||||
eBezTriple_KeyframeType(ts->keyframe_type),
|
||||
flag);
|
||||
if (result.get_count(SingleKeyingResult::SUCCESS) == 0) {
|
||||
result.generate_reports(reports);
|
||||
}
|
||||
}
|
||||
else {
|
||||
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
|
||||
|
|
|
@ -621,17 +621,18 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
|||
|
||||
static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
|
||||
{
|
||||
char msg[UI_MAX_DRAW_STR];
|
||||
if (area == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (area) {
|
||||
if (hasNumInput(&data->num_input)) {
|
||||
char num_str[NUM_STR_REP_LEN];
|
||||
outputNumInput(&data->num_input, num_str, &scene->unit);
|
||||
SNPRINTF(msg, IFACE_("Slip offset: %s"), num_str);
|
||||
}
|
||||
else {
|
||||
SNPRINTF(msg, IFACE_("Slip offset: %d"), offset);
|
||||
}
|
||||
char msg[UI_MAX_DRAW_STR];
|
||||
if (hasNumInput(&data->num_input)) {
|
||||
char num_str[NUM_STR_REP_LEN];
|
||||
outputNumInput(&data->num_input, num_str, &scene->unit);
|
||||
SNPRINTF(msg, IFACE_("Slip offset: %s"), num_str);
|
||||
}
|
||||
else {
|
||||
SNPRINTF(msg, IFACE_("Slip offset: %d"), offset);
|
||||
}
|
||||
|
||||
ED_area_status_text(area, msg);
|
||||
|
|
|
@ -1714,6 +1714,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
|
|||
case CTX_MODE_SCULPT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".grease_pencil_sculpt");
|
||||
break;
|
||||
case CTX_MODE_WEIGHT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".grease_pencil_weight");
|
||||
break;
|
||||
case CTX_MODE_EDIT_POINT_CLOUD:
|
||||
ARRAY_SET_ITEMS(contexts, ".point_cloud_edit");
|
||||
break;
|
||||
|
|
|
@ -121,9 +121,6 @@ static void uiTemplatePaintModeSelection(uiLayout *layout, bContext *C)
|
|||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
if (ob->type != OB_MESH) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Gizmos aren't used in paint modes */
|
||||
if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
|
||||
|
|
|
@ -152,7 +152,8 @@ static blender::VectorSet<Sequence *> query_snap_targets(Scene *scene,
|
|||
return snap_targets;
|
||||
}
|
||||
|
||||
static int seq_get_snap_target_points_count(short snap_mode,
|
||||
static int seq_get_snap_target_points_count(const Scene *scene,
|
||||
short snap_mode,
|
||||
blender::Span<Sequence *> snap_targets)
|
||||
{
|
||||
int count = 2; /* Strip start and end are always used. */
|
||||
|
@ -167,6 +168,10 @@ static int seq_get_snap_target_points_count(short snap_mode,
|
|||
count++;
|
||||
}
|
||||
|
||||
if (snap_mode & SEQ_SNAP_TO_MARKERS) {
|
||||
count += BLI_listbase_count(&scene->markers);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -175,7 +180,8 @@ static bool seq_snap_target_points_build(Scene *scene,
|
|||
TransSeqSnapData *snap_data,
|
||||
blender::Span<Sequence *> snap_targets)
|
||||
{
|
||||
const size_t point_count_target = seq_get_snap_target_points_count(snap_mode, snap_targets);
|
||||
const size_t point_count_target = seq_get_snap_target_points_count(
|
||||
scene, snap_mode, snap_targets);
|
||||
if (point_count_target == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -188,6 +194,13 @@ static bool seq_snap_target_points_build(Scene *scene,
|
|||
i++;
|
||||
}
|
||||
|
||||
if (snap_mode & SEQ_SNAP_TO_MARKERS) {
|
||||
LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
|
||||
snap_data->target_snap_points[i] = marker->frame;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (Sequence *seq : snap_targets) {
|
||||
snap_data->target_snap_points[i] = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
snap_data->target_snap_points[i + 1] = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
|
|
|
@ -50,6 +50,7 @@ set(SRC
|
|||
intern/trim_curves.cc
|
||||
intern/uv_pack.cc
|
||||
intern/uv_parametrizer.cc
|
||||
intern/volume_grid_resample.cc
|
||||
|
||||
GEO_add_curves_on_mesh.hh
|
||||
GEO_curve_constraints.hh
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue