mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-01 22:20:00 -06:00
instance3d: the copy's cache key covers DoF, animated models and env light
The referenced model's solo render goes through the comp camera: its depth of field (focus, aperture, iris, highlights) blurs it, none of which is in the projection matrix — the evaluated Dof is hashed in now (CodeRabbit, review of #2410). A model with an animation clip selected is posed at its layer time (Animation Speed and Looping are static and hashed): the layer time is folded into the key, so every time is its own entry. A model without a clip keeps one key across times, as before. An Environment light's image lights Advanced 3D models, and its source can be any layer's render (or any environment layer) — too open-ended to hash: while one is on, the read is not cached. Each is covered by a render test.
This commit is contained in:
+27
-5
@@ -3,7 +3,7 @@
|
||||
//! cyclic/over-budget graphs or expressions sampled at unknown times.
|
||||
use super::{KeyHasher, hash_debug, hash_values};
|
||||
use crate::EvalCtx;
|
||||
use effectcraft_project::{ItemId, ItemKind, Layer, LayerId, LayerSource, Node, PropGroup};
|
||||
use effectcraft_project::{ItemId, ItemKind, Layer, LayerId, LayerSource, LightKind, Node, PropGroup};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub(super) fn hash(h: &mut KeyHasher, ctx: &EvalCtx, layer: &Layer, effects: Option<usize>) -> Option<()> {
|
||||
@@ -65,9 +65,11 @@ impl Dependencies<'_> {
|
||||
|
||||
/// What a referenced 3D model or primitive layer's solo render depends on: the layer itself
|
||||
/// (geometry, materials, switches, in/out), its animated values and transform at the time,
|
||||
/// the mesh item, the comp's camera and lights at the time (the lights are off in draft 3D,
|
||||
/// and the renderer setting changes the pixels), and the in/out gate (outside the range the
|
||||
/// read is transparent). Comp size and render scale are in the owner's key already.
|
||||
/// the mesh item, the comp's camera (with its depth of field) and its lights at the time
|
||||
/// (the lights are off in draft 3D, and the renderer setting changes the pixels), the model's
|
||||
/// layer time while it plays an animation clip, and the in/out gate (outside the range the
|
||||
/// read is transparent). An Environment light's image can be any layer's render: with one on
|
||||
/// the read is not cached. Comp size and render scale are in the owner's key already.
|
||||
fn soloed_model(&mut self, ctx: &EvalCtx, layer: &Layer) -> Option<()> {
|
||||
self.remaining = self.remaining.checked_sub(1)?;
|
||||
// Expressions sampled at other times: not cacheable, as in the ordinary path.
|
||||
@@ -80,11 +82,31 @@ impl Dependencies<'_> {
|
||||
if let Some(item) = layer.source.item() {
|
||||
hash_debug(self.h, &ctx.project.item(item));
|
||||
}
|
||||
// The solo render goes through the comp's camera and lights.
|
||||
// The solo render goes through the comp's camera and lights. The camera's depth of
|
||||
// field blurs it (focus, aperture, iris, highlights) — none of that is in the
|
||||
// projection hashed above.
|
||||
hash_debug(self.h, &ctx.camera());
|
||||
hash_debug(self.h, &crate::three_d::active_camera(ctx).dof);
|
||||
hash_debug(self.h, &crate::three_d::light::lights_at(ctx));
|
||||
hash_debug(self.h, &ctx.comp.draft_3d);
|
||||
hash_debug(self.h, &ctx.comp.renderer);
|
||||
// An Environment light's image lights Advanced 3D models (its source can be any
|
||||
// layer's render, or any environment layer) — too open-ended to hash: while one is
|
||||
// on (and lighting: Draft 3D lights nothing), don't cache the read.
|
||||
if ctx.comp.renderer == effectcraft_project::Renderer::Advanced3D
|
||||
&& !ctx.comp.draft_3d
|
||||
&& ctx.comp.layers.iter().any(|l| {
|
||||
l.is_light() && l.switches.video && l.is_active_at(ctx.time) && matches!(l.source, LayerSource::Light { kind: LightKind::Environment })
|
||||
})
|
||||
{
|
||||
return None;
|
||||
}
|
||||
// A model with an animation clip selected is posed at its layer time (Animation Speed
|
||||
// and Looping are static, hashed above): every time is its own entry. Without one the
|
||||
// pose is the same at every time: keep the static key.
|
||||
if layer.props.sub("geometryOptions").map_or(0, |g| ctx.e(layer, g, "animation")) != 0 {
|
||||
layer.layer_time(ctx.time).0.hash(self.h);
|
||||
}
|
||||
// Outside the layer's in/out range the read is transparent: fold the gate in, so a
|
||||
// static model renders once inside it and again when it leaves.
|
||||
layer.is_active_at(ctx.time).hash(self.h);
|
||||
|
||||
Reference in New Issue
Block a user