1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Global shader configuration sub-struct extracted from `Config`.
//!
//! Contains all `custom_shader_*` and `cursor_shader_*` top-level config fields.
use serde::{Deserialize, Serialize};
/// Global shader settings for both background (custom) and cursor shaders.
///
/// Extracted from `Config` via `#[serde(flatten)]` for YAML backward-compatibility.
/// Fields serialise at the top level, so existing `config.yaml` files need no changes.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct GlobalShaderConfig {
// ========================================================================
// Background (Custom) Shader Settings
// ========================================================================
/// Custom shader file path (GLSL format, relative to shaders folder or absolute)
/// Shaders are loaded from ~/.config/par-term/shaders/ by default
/// Supports Ghostty/Shadertoy-style GLSL shaders with iTime, iResolution, iChannel0-4
pub custom_shader: Option<String>,
/// Enable or disable the custom shader (even if a path is set)
pub custom_shader_enabled: bool,
/// Enable animation in custom shader (updates iTime uniform each frame)
/// When disabled, iTime is fixed at 0.0 for static effects
pub custom_shader_animation: bool,
/// Animation speed multiplier for custom shader (1.0 = normal speed)
pub custom_shader_animation_speed: f32,
/// Text opacity when using custom shader (0.0 = transparent, 1.0 = fully opaque)
/// This allows text to remain readable while the shader effect shows through the background
pub custom_shader_text_opacity: f32,
/// When enabled, the shader receives the full rendered terminal content (text + background)
/// and can manipulate/distort it. When disabled (default), the shader only provides
/// a background and text is composited on top cleanly.
pub custom_shader_full_content: bool,
/// Brightness multiplier for custom shader output (0.05 = very dark, 1.0 = full brightness)
/// This dims the shader background to improve text readability
pub custom_shader_brightness: f32,
/// Texture file path for custom shader iChannel0 (optional, Shadertoy compatible)
/// Supports ~ for home directory. Example: "~/textures/noise.png"
pub custom_shader_channel0: Option<String>,
/// Texture file path for custom shader iChannel1 (optional)
pub custom_shader_channel1: Option<String>,
/// Texture file path for custom shader iChannel2 (optional)
pub custom_shader_channel2: Option<String>,
/// Texture file path for custom shader iChannel3 (optional)
pub custom_shader_channel3: Option<String>,
/// Cubemap texture path prefix for custom shaders (optional)
/// Expects 6 face files: {prefix}-px.{ext}, -nx.{ext}, -py.{ext}, -ny.{ext}, -pz.{ext}, -nz.{ext}
/// Supported formats: .png, .jpg, .jpeg, .hdr
/// Example: "textures/cubemaps/env-outside" will load env-outside-px.png, etc.
pub custom_shader_cubemap: Option<String>,
/// Enable cubemap sampling in custom shaders
/// When enabled and a cubemap path is set, iCubemap uniform is available in shaders
pub custom_shader_cubemap_enabled: bool,
/// Use the app's background image as iChannel0 for custom shaders
/// When enabled, the configured background image is bound as iChannel0 instead of
/// the custom_shader_channel0 texture. This allows shaders to incorporate the
/// background image without requiring a separate texture file.
pub custom_shader_use_background_as_channel0: bool,
/// Blend mode hint exposed to shaders using the app background as iChannel0.
#[serde(default = "crate::defaults::background_channel0_blend_mode")]
pub custom_shader_background_channel0_blend_mode: crate::types::ShaderBackgroundBlendMode,
/// Reduce shader intensity only under terminal text/content for readability.
pub custom_shader_auto_dim_under_text: bool,
/// Auto-dim strength under terminal text/content (0.0 = no extra dim, 1.0 = black).
pub custom_shader_auto_dim_strength: f32,
/// Temporary low-power/readability mode for quick toggles.
pub custom_shader_readability_mode: bool,
/// Brightness cap used while readability mode is enabled.
pub custom_shader_readability_brightness: f32,
// ========================================================================
// Cursor Shader Settings (separate from background shader)
// ========================================================================
/// Cursor shader file path (GLSL format, relative to shaders folder or absolute)
/// This is a separate shader specifically for cursor effects (trails, glows, etc.)
pub cursor_shader: Option<String>,
/// Enable or disable the cursor shader (even if a path is set)
pub cursor_shader_enabled: bool,
/// Enable animation in cursor shader (updates iTime uniform each frame)
pub cursor_shader_animation: bool,
/// Animation speed multiplier for cursor shader (1.0 = normal speed)
pub cursor_shader_animation_speed: f32,
/// Cursor color for shader effects [R, G, B] (0-255)
/// This color is passed to the shader via iCursorShaderColor uniform
pub cursor_shader_color: [u8; 3],
/// Duration of cursor trail effect in seconds
/// Passed to shader via iCursorTrailDuration uniform
pub cursor_shader_trail_duration: f32,
/// Radius of cursor glow effect in pixels
/// Passed to shader via iCursorGlowRadius uniform
pub cursor_shader_glow_radius: f32,
/// Intensity of cursor glow effect (0.0 = none, 1.0 = full)
/// Passed to shader via iCursorGlowIntensity uniform
pub cursor_shader_glow_intensity: f32,
/// Hide the default cursor when cursor shader is enabled
/// When true and cursor_shader_enabled is true, the normal cursor is not drawn
/// This allows cursor shaders to fully replace the cursor rendering
pub cursor_shader_hides_cursor: bool,
/// Disable cursor shader while in alt screen (vim, less, htop)
/// Keeps current behavior by default for TUI compatibility
pub cursor_shader_disable_in_alt_screen: bool,
}
impl Default for GlobalShaderConfig {
fn default() -> Self {
Self {
custom_shader: None,
custom_shader_enabled: crate::defaults::bool_true(),
custom_shader_animation: crate::defaults::bool_true(),
custom_shader_animation_speed: crate::defaults::custom_shader_speed(),
custom_shader_text_opacity: crate::defaults::text_opacity(),
custom_shader_full_content: crate::defaults::bool_false(),
custom_shader_brightness: crate::defaults::custom_shader_brightness(),
custom_shader_channel0: None,
custom_shader_channel1: None,
custom_shader_channel2: None,
custom_shader_channel3: None,
custom_shader_cubemap: None,
custom_shader_cubemap_enabled: crate::defaults::cubemap_enabled(),
custom_shader_use_background_as_channel0: crate::defaults::use_background_as_channel0(),
custom_shader_background_channel0_blend_mode:
crate::defaults::background_channel0_blend_mode(),
custom_shader_auto_dim_under_text: crate::defaults::bool_false(),
custom_shader_auto_dim_strength: 0.35,
custom_shader_readability_mode: crate::defaults::bool_false(),
custom_shader_readability_brightness: 0.35,
cursor_shader: None,
cursor_shader_enabled: crate::defaults::bool_false(),
cursor_shader_animation: crate::defaults::bool_true(),
cursor_shader_animation_speed: crate::defaults::custom_shader_speed(),
cursor_shader_color: crate::defaults::cursor_shader_color(),
cursor_shader_trail_duration: crate::defaults::cursor_trail_duration(),
cursor_shader_glow_radius: crate::defaults::cursor_glow_radius(),
cursor_shader_glow_intensity: crate::defaults::cursor_glow_intensity(),
cursor_shader_hides_cursor: crate::defaults::bool_false(),
cursor_shader_disable_in_alt_screen:
crate::defaults::cursor_shader_disable_in_alt_screen(),
}
}
}