Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions crates/compositor/src/compositor_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ use crate::ffi::AVFrame;
// Re-exports que le code partage (live.rs, compositor-view-napi) consomme via
// `crate::compositor::…`, a l'identique de `compositor_macos`.
pub use crate::frame_geometry::{
live_params_from_scene, webcam_shape_code, FIXTURE_FRAMES, LayerCB, LiveParams, OUT_H, OUT_W,
chroma_key_uniform, live_params_from_scene, webcam_shape_code, FIXTURE_FRAMES, LayerCB,
LiveParams, OUT_H, OUT_W,
};
use crate::frame_geometry::{
cursor_sprite_dst, parse_hex, plan_cursor, plan_frame, CursorPlacement, CursorPlanInput,
Expand All @@ -44,10 +45,22 @@ use crate::scene::{Scene, SceneBackground};
const LAYER_WGSL: &str = include_str!("vk_shaders/layer.wgsl");
const BLUR_WGSL: &str = include_str!("vk_shaders/blur.wgsl");

/// `&LayerCB` -> `&[u8; 128]`. `LayerCB` est `#[repr(C, align(16))]`, son layout
/// EST le buffer uniforme WGSL (16 vec4 + 1 vec2 + 2 f32 = 128 octets).
/// `&LayerCB` -> ses octets bruts. `LayerCB` est `#[repr(C, align(16))]`, son layout EST le
/// buffer uniforme WGSL.
///
/// La taille est DÉRIVÉE, pas écrite : elle l'était en dur (128), ce qui rendait tout ajout de
/// champ silencieusement tronquant — le struct grandit, la copie non, et le shader lit du
/// vieux contenu sans que rien ne lève. `min_binding_size` plus bas suit la même règle.
fn layer_bytes(cb: &LayerCB) -> &[u8] {
unsafe { std::slice::from_raw_parts(cb as *const LayerCB as *const u8, 128) }
unsafe {
std::slice::from_raw_parts(cb as *const LayerCB as *const u8, std::mem::size_of::<LayerCB>())
}
}

/// Taille du buffer uniforme de calque, pour `min_binding_size`. `unwrap` : `size_of` d'un
/// struct non vide n'est jamais 0, la seule condition d'échec de `BufferSize::new`.
fn layer_uniform_size() -> wgpu::BufferSize {
wgpu::BufferSize::new(std::mem::size_of::<LayerCB>() as u64).unwrap()
}

/// Une copie RT -> staging DEJA SOUMISE, dont le mapping est arme mais pas
Expand Down Expand Up @@ -226,7 +239,7 @@ impl Compositor {
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: wgpu::BufferSize::new(128),
min_binding_size: Some(layer_uniform_size()),
},
count: None,
},
Expand Down Expand Up @@ -308,7 +321,7 @@ impl Compositor {
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: wgpu::BufferSize::new(128),
min_binding_size: Some(layer_uniform_size()),
},
count: None,
},
Expand Down Expand Up @@ -1249,6 +1262,9 @@ impl Compositor {
// precedente, et un rect source qui ne correspond pas au calque
// dessine ferait diverger la trainee vers une zone de la texture qui
// n'a jamais ete affichee. Seul `dst_prev` porte le mouvement.
//
// Incrustation couleur : le SEUL draw qui la porte (cf. `compositor_windows`).
let (chroma_key, chroma_fx) = chroma_key_uniform(&lp);
let cb = LayerCB {
dst: g.w_dst,
src: [u0, cv0, u1, cv1],
Expand All @@ -1259,6 +1275,8 @@ impl Compositor {
src_prev: [u0, cv0, u1, cv1],
dst_prev: g.w_dst_prev,
mb: [g.mb_taps, 1.0, 1.0, 0.0],
chroma_key,
chroma_fx,
..Default::default()
};
self.make_bind(&cb, Some((wy, wuv)), &dummy)
Expand All @@ -1268,9 +1286,13 @@ impl Compositor {
// vertical-stack) : la camera y est collee a l'ecran comme une tuile,
// et une ombre entre les deux dessinerait une couture. Meme condition
// que macOS.
// `!lp.chroma_enabled` : cf. `compositor_windows` — l'ombre est celle de la bulle
// opaque, et l'incrustation supprime la bulle. La garder laisse un rectangle sombre
// visible derriere le sujet detoure.
let webcam_shadow = (cfg.shadow
&& g.shape_fade > 0.0
&& webcam_draw.is_some()
&& !lp.chroma_enabled
&& !matches!(
g.scene_preset.as_deref(),
Some("dual-frame") | Some("vertical-stack")
Expand Down
17 changes: 15 additions & 2 deletions crates/compositor/src/compositor_macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ use crate::ffi::AVFrame;
// les deux backends — cf. `frame_geometry`, qui documente les divergences que
// l'unification a corrigées.
pub use crate::frame_geometry::{
live_params_from_scene, webcam_shape_code, FIXTURE_FRAMES, LayerCB, LiveParams, OUT_H, OUT_W,
chroma_key_uniform, live_params_from_scene, webcam_shape_code, FIXTURE_FRAMES, LayerCB,
LiveParams, OUT_H, OUT_W,
};
use crate::frame_geometry::{parse_hex, FrameGeometryInput, SCREEN_SHADOW_OFFSET_FRAC,
SCREEN_SHADOW_SPREAD_FRAC, WEBCAM_SHADOW_OFFSET_FRAC, WEBCAM_SHADOW_OPACITY,
Expand Down Expand Up @@ -1618,7 +1619,15 @@ impl Compositor {
g.scene_preset.as_deref(),
Some("dual-frame") | Some("vertical-stack")
);
if cfg.shadow && !webcam_is_block && g.shape_fade > 0.0 {
// ...et PAS quand l'incrustation couleur est active. L'ombre est celle de la
// BULLE : un rectangle arrondi opaque qui flotte au-dessus de la scene. Detourer
// le fond supprime cette bulle — il ne reste que le sujet — et l'ombre devient
// alors un rectangle sombre visible DERRIERE lui, la ou le fond vient d'etre
// rendu transparent. Mesure sur un export de controle : le fond detoure ressortait
// a 0,65x la couleur de l'ecran, soit exactement WEBCAM_SHADOW_OPACITY.
// Meme raison que `shape_fade` retire l'ombre au plein ecran : plus de bulle,
// plus d'ombre.
if cfg.shadow && !webcam_is_block && g.shape_fade > 0.0 && !lp.chroma_enabled {
self.draw_shadow(
enc,
g.w_dst,
Expand All @@ -1629,6 +1638,8 @@ impl Compositor {
WEBCAM_SHADOW_OPACITY * g.shape_fade,
);
}
// Incrustation couleur : le SEUL draw qui la porte (cf. `compositor_windows`).
let (chroma_key, chroma_fx) = chroma_key_uniform(&lp);
self.draw_video(
enc,
&LayerCB {
Expand All @@ -1641,6 +1652,8 @@ impl Compositor {
src_prev: [u0, cv0, u1, cv1],
dst_prev: g.w_dst_prev,
mb: [g.mb_taps, 1.0, 1.0, 0.0],
chroma_key,
chroma_fx,
..Default::default()
},
wy,
Expand Down
21 changes: 18 additions & 3 deletions crates/compositor/src/compositor_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::config::Cfg;
// pour le pourquoi. `pub use` sur les constantes : `pipeline_windows.rs`, `live.rs` et
// `crates/poc-d3d/src/app.rs` les lisent via `crate::compositor::…`, et ce chemin doit
// rester valable.
pub use crate::frame_geometry::{live_params_from_scene, webcam_shape_code, LayerCB,
LiveParams, FIXTURE_FRAMES, HALF_H, HALF_W, OUT_H, OUT_W};
pub use crate::frame_geometry::{chroma_key_uniform, live_params_from_scene, webcam_shape_code,
LayerCB, LiveParams, FIXTURE_FRAMES, HALF_H, HALF_W, OUT_H, OUT_W};
use crate::frame_geometry::{
cover_crop_uv, cover_uv_rect, cursor_sprite_dst, decode_data_uri, ease_in_out_cubic, lerp,
lerp4, parse_hex, preset_placements, remap_box, screen_source_rect, timeline, CursorPlacement,
Expand Down Expand Up @@ -1538,7 +1538,15 @@ impl Compositor {
scene_preset.as_deref(),
Some("dual-frame") | Some("vertical-stack"),
);
if cfg.shadow && !webcam_is_block && shape_fade > 0.0 {
// ...et PAS quand l'incrustation couleur est active. L'ombre est celle de la
// BULLE : un rectangle arrondi opaque qui flotte au-dessus de la scene. Detourer
// le fond supprime cette bulle — il ne reste que le sujet — et l'ombre devient
// alors un rectangle sombre visible DERRIERE lui, la ou le fond vient d'etre
// rendu transparent. Mesure sur un export de controle : le fond detoure ressortait
// a 0,65x la couleur de l'ecran, soit exactement WEBCAM_SHADOW_OPACITY.
// Meme raison que `shape_fade` retire l'ombre au plein ecran : plus de bulle,
// plus d'ombre.
if cfg.shadow && !webcam_is_block && shape_fade > 0.0 && !lp.chroma_enabled {
let strength = WEBCAM_SHADOW_OPACITY * shape_fade;
self.draw_shadow(
w_dst,
Expand All @@ -1549,6 +1557,11 @@ impl Compositor {
strength,
);
}
// Incrustation couleur : le SEUL draw qui la porte. L'écran partage le mode 0 et
// garde `..Default::default()`, donc ses deux `float4` sont nuls et la branche du
// shader est uniformément fausse pour lui — coût nul, et aucun risque d'incruster
// l'enregistrement d'écran.
let (chroma_key, chroma_fx) = chroma_key_uniform(&lp);
self.draw_video(
&LayerCB {
dst: w_dst,
Expand All @@ -1560,6 +1573,8 @@ impl Compositor {
src_prev: [u0, sv0, u1, sv1], // src fixe (pas de zoom webcam)
dst_prev: w_dst_prev,
mb: [mb_taps, 1.0, 1.0, 0.0],
chroma_key,
chroma_fx,
..Default::default()
},
&wy,
Expand Down
Loading