Skip to content

Commit 2588e62

Browse files
committed
MouseEffects v1.0.28
Release Notes New Features Simulation-Guided Correction (ColorBlindnessNG) - Smart pixel detection: Uses CVD simulation to identify which pixels are actually affected by color blindness before applying correction - Adjustable sensitivity: Control detection aggressiveness (0.5-5.0) - conservative to aggressive - Natural results: Leaves unaffected colors unchanged, only correcting pixels that need it - Algorithm choice: Select between Machado (RGB) or Strict (LMS) for detection Post-Correction Simulation ("Re-simulate for Verification") - Verify correction effectiveness: Apply CVD simulation AFTER correction to see how corrected colors appear to colorblind users - Non-colorblind validation: Helps sighted users confirm that previously confusing colors are now distinguishable - Independent controls: Separate algorithm, CVD type, and intensity settings per zone - Pipeline: Original → Correction → Simulation visualization Bug Fixes - Fixed overlay topmost issues: Dialogs and settings window now properly appear above the overlay without causing z-order problems when closed - Fixed preset persistence: Selected presets now correctly restore on app restart (was reverting to "Custom") - Fixed preset saving location: Custom presets now save to AppData instead of plugin directory - Fixed configuration key mismatch: WhiteProtection settings now properly persist between sessions - Fixed Zone2/Zone3 loading: All 4 zones now correctly load their settings on startup Improvements - White protection minimum: Changed minimum value from 0.0 to 0.01 for better color preservation - Documentation updates: README and Wiki updated with new feature documentation
1 parent 78c83f4 commit 2588e62

9 files changed

Lines changed: 804 additions & 22 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ MouseEffects is a modular, plugin-based application that renders beautiful visua
3030
| **Laser Work** | Directional lasers shooting from cursor with collision detection |
3131
| **Screen Distortion** | Real-time lens/ripple distortion effect |
3232
| **Color Blindness** | CVD simulation & correction with 17 filter types (Machado/Strict algorithms), zone layouts, and comparison view |
33-
| **Color Blindness NG** | Next-gen CVD plugin with per-zone configuration, LUT-based correction, custom presets, Circle/Rectangle cursor-following modes with soft edge blending |
33+
| **Color Blindness NG** | Next-gen CVD plugin with per-zone configuration, LUT-based correction, custom presets, Circle/Rectangle cursor-following modes, Simulation-Guided Correction, and Post-Correction Verification |
3434
| **Radial Dithering** | Bayer-pattern dithering effect around cursor |
3535
| **Tile Vibration** | Vibrating tiles that capture and display screen content |
3636
| **Water Ripple** | Expanding water ripples on click with realistic wave interference |

Wiki/Features.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,45 @@ Effects in MouseEffects can:
196196
| **Geometric Rendering** | Lines, circles, rectangles with shaders |
197197
| **Texture Sampling** | Use screen content as texture source |
198198

199+
## Color Vision Accessibility (ColorBlindnessNG)
200+
201+
The ColorBlindnessNG plugin provides advanced accessibility features for color vision deficiency (CVD):
202+
203+
### Simulation Mode
204+
Simulates how people with various types of color blindness perceive colors:
205+
- **Machado Algorithm**: RGB-space matrices from Machado et al. (2009) research
206+
- **Strict LMS Algorithm**: Physiologically-accurate LMS colorspace processing
207+
- **8 CVD Types**: Protanopia, Protanomaly, Deuteranopia, Deuteranomaly, Tritanopia, Tritanomaly, Achromatopsia, Achromatomaly
208+
209+
### Correction Mode
210+
Helps colorblind users distinguish colors using LUT-based remapping:
211+
- **Per-Channel Control**: Independent red, green, blue correction with customizable gradients
212+
- **Multiple Presets**: Built-in presets for common CVD types plus custom preset support
213+
- **Application Modes**: Full Channel, Dominant Only, or Threshold-based correction
214+
- **Gradient Interpolation**: Linear RGB, Perceptual LAB, or HSL color space blending
215+
216+
### Advanced Features (v1.0.28+)
217+
218+
#### Simulation-Guided Correction
219+
Uses CVD simulation to detect which pixels are affected before applying correction:
220+
- Only corrects pixels that would actually be impacted by the CVD type
221+
- Configurable sensitivity (0.5-5.0) controls detection aggressiveness
222+
- Leaves unaffected colors unchanged for more natural results
223+
224+
#### Post-Correction Simulation (Re-simulate for Verification)
225+
Applies CVD simulation AFTER correction to verify effectiveness:
226+
- Non-colorblind users can see how corrected colors appear to CVD users
227+
- Helps validate that previously confusing colors are now distinguishable
228+
- Independent algorithm and intensity controls per zone
229+
230+
### Display Modes
231+
- **Fullscreen**: Apply effect to entire screen
232+
- **Split Modes**: Vertical, Horizontal, or Quadrant splits for comparison
233+
- **Circle/Rectangle**: Cursor-following shapes with configurable size and soft edges
234+
- **Comparison Mode**: Duplicate screen in each zone with virtual cursor projection
235+
236+
See [Plugins Reference](Plugins.md#color-blindness-ng) for complete settings documentation
237+
199238
## Extensibility
200239

201240
### Custom Effects

Wiki/Plugins.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ Next-generation color vision deficiency (CVD) simulation and correction plugin w
358358
- **Per-zone architecture**: Up to 4 independent zones, each configurable as Original, Simulation, or Correction
359359
- **14 CVD simulation types** across Machado (RGB) and Strict (LMS) algorithms
360360
- **LUT-based correction**: Per-channel color remapping with customizable gradients
361+
- **Simulation-Guided Correction** (v1.0.28+): Uses CVD simulation to detect affected pixels before applying correction
362+
- **Post-Correction Simulation** (v1.0.28+): Re-simulate CVD after correction to verify effectiveness
363+
- **Sensitivity control** (v1.0.28+): Adjustable detection sensitivity for simulation-guided correction
361364
- **Real comparison mode**: Full screen duplicated in each zone with virtual cursor projection
362365
- **Custom preset system**: Save, load, export, and import correction presets
363366
- **Multiple split modes**: Fullscreen, Split Vertical/Horizontal, Quadrants, Circle, Rectangle
@@ -459,7 +462,53 @@ Each zone has three channel LUTs (Red, Green, Blue) with these settings:
459462
| `zone{n}_{color}Strength` | float | 0-1 | 1.0 | Channel correction strength |
460463
| `zone{n}_{color}StartColor` | string | hex | varies | LUT gradient start color |
461464
| `zone{n}_{color}EndColor` | string | hex | varies | LUT gradient end color |
462-
| `zone{n}_{color}WhiteProtection` | float | 0-1 | 0.0 | Protect whites from correction |
465+
| `zone{n}_{color}WhiteProtection` | float | 0.01-1 | 0.01 | Protect whites from correction |
466+
467+
### Simulation-Guided Correction (v1.0.28+)
468+
469+
An optional mode that uses CVD simulation to detect which pixels are affected before applying LUT correction. This ensures only pixels that would actually be affected by CVD receive correction, leaving unaffected colors unchanged.
470+
471+
**How It Works:**
472+
1. Simulates the selected CVD type on the original pixel
473+
2. Calculates the error between original and simulated colors
474+
3. Uses the error magnitude to determine a blend weight (0-1)
475+
4. Applies LUT correction proportionally to the detected error
476+
477+
| Setting | Type | Range | Default | Description |
478+
|---------|------|-------|---------|-------------|
479+
| `zone{n}_simGuidedEnabled` | bool | - | false | Enable simulation-guided detection |
480+
| `zone{n}_simGuidedAlgorithm` | int | 0-1 | 0 | 0=Machado, 1=Strict |
481+
| `zone{n}_simGuidedFilterType` | int | 1-14 | 3 | CVD type to detect |
482+
| `zone{n}_simGuidedSensitivity` | float | 0.5-5.0 | 2.0 | Detection sensitivity (higher = more aggressive) |
483+
484+
**Sensitivity Guide:**
485+
- **0.5-1.0**: Conservative - only strong color differences trigger correction
486+
- **2.0**: Balanced default - moderate detection threshold
487+
- **3.0-5.0**: Aggressive - even subtle color differences trigger correction
488+
489+
### Post-Correction Simulation (Re-simulate for Verification) (v1.0.28+)
490+
491+
Applies CVD simulation AFTER correction to visualize how corrected colors appear to colorblind users. This helps non-colorblind users verify that corrections are effective.
492+
493+
**Use Case:**
494+
1. Apply color correction for deuteranopia
495+
2. Enable "Re-simulate for Verification" with deuteranopia
496+
3. Screen shows: Original → Correction → Simulation
497+
4. See what a deuteranope would perceive after correction is applied
498+
5. Verify that previously confusing colors are now distinguishable
499+
500+
| Setting | Type | Range | Default | Description |
501+
|---------|------|-------|---------|-------------|
502+
| `zone{n}_postSimEnabled` | bool | - | false | Enable post-correction simulation |
503+
| `zone{n}_postSimAlgorithm` | int | 0-1 | 0 | 0=Machado, 1=Strict |
504+
| `zone{n}_postSimFilterType` | int | 1-14 | 3 | CVD type to simulate |
505+
| `zone{n}_postSimIntensity` | float | 0-1 | 1.0 | Simulation blend intensity |
506+
507+
**Key Distinction:**
508+
- **Simulation-Guided Correction**: Uses simulation to DETECT which pixels need correction
509+
- **Post-Correction Simulation**: Uses simulation AFTER correction for VISUALIZATION
510+
511+
Both features can be enabled independently on the same zone
463512

464513
#### Application Modes
465514

plugins/MouseEffects.Effects.ColorBlindnessNG/ColorBlindnessNGEffect.cs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,16 @@ private void LoadZoneConfiguration(int zoneIndex)
391391
if (Configuration.TryGet($"{prefix}simGuidedSensitivity", out float simGuidedSensitivity))
392392
z.SimulationGuidedSensitivity = simGuidedSensitivity;
393393

394+
// Post-correction simulation settings
395+
if (Configuration.TryGet($"{prefix}postSimEnabled", out bool postSimEnabled))
396+
z.PostCorrectionSimEnabled = postSimEnabled;
397+
if (Configuration.TryGet($"{prefix}postSimAlgorithm", out int postSimAlgorithm))
398+
z.PostCorrectionSimAlgorithm = (SimulationAlgorithm)postSimAlgorithm;
399+
if (Configuration.TryGet($"{prefix}postSimFilterType", out int postSimFilterType))
400+
z.PostCorrectionSimFilterType = postSimFilterType;
401+
if (Configuration.TryGet($"{prefix}postSimIntensity", out float postSimIntensity))
402+
z.PostCorrectionSimIntensity = postSimIntensity;
403+
394404
// Red channel
395405
bool needsUpdate = z.LutsNeedUpdate;
396406
LoadChannelConfiguration(z.RedChannel, $"{prefix}red", ref needsUpdate);
@@ -555,6 +565,14 @@ private ColorBlindnessNGParams BuildConstantBuffer(Vector2 viewportSize)
555565
effectiveSimGuidedFilterType = z.SimulationGuidedFilterType + 6;
556566
}
557567

568+
// Calculate effective filter type for post-correction simulation
569+
int effectivePostSimFilterType = z.PostCorrectionSimFilterType;
570+
if (z.PostCorrectionSimAlgorithm == SimulationAlgorithm.Strict &&
571+
z.PostCorrectionSimFilterType > 0 && z.PostCorrectionSimFilterType <= 6)
572+
{
573+
effectivePostSimFilterType = z.PostCorrectionSimFilterType + 6;
574+
}
575+
558576
var zoneParams = new ZoneParams
559577
{
560578
Mode = (float)z.Mode,
@@ -573,7 +591,10 @@ private ColorBlindnessNGParams BuildConstantBuffer(Vector2 viewportSize)
573591
BlueWhiteProtection = z.BlueChannel.WhiteProtection,
574592
SimulationGuidedEnabled = z.SimulationGuidedEnabled ? 1.0f : 0.0f,
575593
SimulationGuidedFilterType = effectiveSimGuidedFilterType,
576-
SimulationGuidedSensitivity = z.SimulationGuidedSensitivity
594+
SimulationGuidedSensitivity = z.SimulationGuidedSensitivity,
595+
PostCorrectionSimEnabled = z.PostCorrectionSimEnabled ? 1.0f : 0.0f,
596+
PostCorrectionSimFilterType = effectivePostSimFilterType,
597+
PostCorrectionSimIntensity = z.PostCorrectionSimIntensity
577598
};
578599

579600
switch (i)
@@ -627,7 +648,7 @@ private static string LoadEmbeddedShader(string name)
627648

628649
/// <summary>
629650
/// Per-zone parameters packed for shader.
630-
/// Size: 80 bytes (20 floats)
651+
/// Size: 96 bytes (24 floats)
631652
/// </summary>
632653
[StructLayout(LayoutKind.Sequential)]
633654
private struct ZoneParams
@@ -653,16 +674,21 @@ private struct ZoneParams
653674
public float SimulationGuidedFilterType; // CVD type for detection
654675

655676
public float SimulationGuidedSensitivity; // Sensitivity multiplier for detection
656-
public float _padding1;
677+
public float PostCorrectionSimEnabled; // 1.0 = apply CVD simulation AFTER correction
678+
public float PostCorrectionSimFilterType; // CVD type for post-correction simulation
679+
public float PostCorrectionSimIntensity; // Intensity of post-correction simulation
680+
681+
public float _padding1; // Padding for 16-byte alignment
657682
public float _padding2;
658683
public float _padding3;
684+
public float _padding4;
659685
}
660686

661687
/// <summary>
662688
/// Full constant buffer for shader.
663-
/// Size: 48 (global) + 4 * 80 (zones) = 368 bytes
689+
/// Size: 48 (global) + 4 * 96 (zones) = 432 bytes
664690
/// </summary>
665-
[StructLayout(LayoutKind.Sequential, Size = 368)]
691+
[StructLayout(LayoutKind.Sequential, Size = 432)]
666692
private struct ColorBlindnessNGParams
667693
{
668694
// Global parameters (48 bytes)

plugins/MouseEffects.Effects.ColorBlindnessNG/Shaders/ColorBlindnessNG.hlsl

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct PSInput
1313
};
1414

1515
// ============================================================================
16-
// Per-Zone Parameters Structure (80 bytes each = 20 floats, 16-byte aligned)
16+
// Per-Zone Parameters Structure (96 bytes each = 24 floats, 16-byte aligned)
1717
// ============================================================================
1818

1919
struct ZoneParams
@@ -39,13 +39,18 @@ struct ZoneParams
3939
float SimulationGuidedFilterType; // CVD type for detection (0=None, 1-6=Machado, 7-12=Strict)
4040

4141
float SimulationGuidedSensitivity; // Sensitivity multiplier (0.5 = conservative, 5.0 = aggressive)
42-
float _padding1;
42+
float PostCorrectionSimEnabled; // 1.0 = apply CVD simulation AFTER correction (for verification)
43+
float PostCorrectionSimFilterType; // CVD type for post-correction simulation (1-14)
44+
float PostCorrectionSimIntensity; // Intensity of post-correction simulation (0-1)
45+
46+
float _padding1; // Padding for 16-byte alignment
4347
float _padding2;
4448
float _padding3;
49+
float _padding4;
4550
};
4651

4752
// ============================================================================
48-
// Constant Buffer (48 + 80*4 = 368 bytes total)
53+
// Constant Buffer (48 + 96*4 = 432 bytes total)
4954
// ============================================================================
5055

5156
cbuffer ColorBlindnessNGParams : register(b0)
@@ -695,23 +700,33 @@ float3 ProcessZone(float3 color, ZoneParams zone, int zoneIndex)
695700
if (zone.Mode < 1.5)
696701
{
697702
processedColor = ApplySimulation(color, zone.SimulationFilterType);
703+
// Apply intensity blend for simulation mode
704+
return lerp(color, processedColor, zone.Intensity);
698705
}
706+
699707
// Mode 2 = Correction
708+
// Call zone-specific LUT function
709+
if (zoneIndex == 0)
710+
processedColor = ApplyLUTCorrectionZone0(color, zone);
711+
else if (zoneIndex == 1)
712+
processedColor = ApplyLUTCorrectionZone1(color, zone);
713+
else if (zoneIndex == 2)
714+
processedColor = ApplyLUTCorrectionZone2(color, zone);
700715
else
716+
processedColor = ApplyLUTCorrectionZone3(color, zone);
717+
718+
// Apply intensity blend for correction
719+
processedColor = lerp(color, processedColor, zone.Intensity);
720+
721+
// Post-correction simulation: Apply CVD simulation AFTER correction
722+
// This allows non-colorblind users to verify how corrected colors appear to CVD users
723+
if (zone.PostCorrectionSimEnabled > 0.5)
701724
{
702-
// Call zone-specific LUT function
703-
if (zoneIndex == 0)
704-
processedColor = ApplyLUTCorrectionZone0(color, zone);
705-
else if (zoneIndex == 1)
706-
processedColor = ApplyLUTCorrectionZone1(color, zone);
707-
else if (zoneIndex == 2)
708-
processedColor = ApplyLUTCorrectionZone2(color, zone);
709-
else
710-
processedColor = ApplyLUTCorrectionZone3(color, zone);
725+
float3 simulated = ApplySimulation(processedColor, zone.PostCorrectionSimFilterType);
726+
processedColor = lerp(processedColor, simulated, zone.PostCorrectionSimIntensity);
711727
}
712728

713-
// Apply intensity blend
714-
return lerp(color, processedColor, zone.Intensity);
729+
return processedColor;
715730
}
716731

717732
// ============================================================================

0 commit comments

Comments
 (0)