Files
HMS MediaEngine Agent 362e089be0 AUFGERAUMT: Root auf 10 sichtbare Elemente reduziert
Der Nutzer hat recht: Der Ordner war voller Entwicklungs-Muell.
Jetzt ist sauber getrennt:

ROOT (was der Nutzer sieht und braucht):
- run.py                     = das Programm
- hms_app/                   = der Anwendungscode
- HMS MediaEngine.app        = macOS Doppelklick-Starter
- HMS-Start.vbs              = Windows Doppelklick-Starter
- HMS-Install.vbs             = Windows Erst-Installation
- HMS-Mac-Install.command     = macOS Homebrew-Installation
- HMS-Portable-Install.command = macOS Portable-Installation (16GB-Fix)
- installer_gui.py           = grafischer Installer
- launcher.pyw + launcher_core.py = interne Start-Logik
- LIESMICH.txt               = 10-Zeilen-Kurzanleitung
- .gitignore

_entwicklung/ (alles andere, NICHT benoetigt):
- packages/ apps/ native/ plugins/ tools/ schemas/ tests/ docs/
  build/ fixture_profiles/
- PLAN.md STATUS.md ERRORS.md TEST_REPORT.md CHANGELOG.md README.md
- pyproject.toml uv.lock setup_*.sh/ps1 make_mac_app.py

Diese Trennung gilt ab sofort fuer alle Commits. Der Nutzer kann
_entwicklung/ loeschen wenn er Platz braucht - die App laeuft ohne.

Verifiziert: App startet nach Aufraeumen unveraendert (Health 200).
2026-09-11 23:44:06 +02:00

240 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Shader-Vertrag
Dieses Dokument beschreibt den verbindlichen Shader-Vertrag für Plugin-Shader. Grundlage sind PLAN.md §14.4 (Standard-Shaderinputs) und die eingebauten Beispiel-Shader des Vignette-Plugins (`plugins/builtin/filters/com.hms.fx.vignette/shaders/`).
## Standard-Uniform-Satz (§14.4)
Jeder Shader erhält nach Bedarf folgende semantische Inputs:
| Semantische ID | Typ | Beschreibung |
| --- | --- | --- |
| `u_input_texture` | Textur | Eingangs-Textur (bei Filtern) |
| `u_resolution` | vec2/float4 | Auflösung in Pixeln (`xy`) |
| `u_time_seconds` | float | Zeit in Sekunden |
| `u_delta_seconds` | float | Zeit seit dem letzten Frame |
| `u_frame_index` | float | Frame-Index |
| `u_layer_opacity` | float | Opazität des Layers |
| `u_audio_rms` | float | Audio-RMS |
| `u_audio_peak` | float | Audio-Peak |
| `u_audio_bass` | float | Audio-Bass |
| `u_audio_mid` | float | Audio-Mid |
| `u_audio_treble` | float | Audio-Treble |
| `u_audio_beat` | float | Audio-Beat |
| deklarierte Pluginparameter | float | Parameter aus `plugin.json` |
Semantische Input-IDs, Typen, Wertebereiche, Farbräume und Texturkonventionen sind Teil der versionierten Plugin-API. Backendadapter binden sie an HLSL-Konstanten beziehungsweise GLSL-Uniforms; Projekte referenzieren niemals konkrete Variablennamen eines Backends (PLAN.md §14.4).
## HLSL (D3D11) cbuffer-Layout
Im HLSL-Backend liegen die Standard-Uniforms und Pluginparameter in einem Konstantenpuffer (`cbuffer`). Das Vignette-Beispiel (`shaders/d3d11/main.hlsl`) zeigt das Layout:
```hlsl
Texture2D u_input_texture : register(t0);
SamplerState u_sampler : register(s0);
cbuffer hms_params : register(b0)
{
float4 u_resolution; // xy = Auflösung in Pixeln
float u_time_seconds;
float u_delta_seconds;
float u_frame_index;
float u_layer_opacity;
float u_audio_rms;
float u_audio_peak;
float u_audio_bass;
float u_audio_mid;
float u_audio_treble;
float u_audio_beat;
float param_amount;
float param_radius;
float param_softness;
float param_roundness;
float param_center_x;
float param_center_y;
float param_color_r;
float param_color_g;
float param_color_b;
float param_invert; // 0 = abdunkeln, 1 = aufhellen
float param_mix;
float _pad0;
float _pad1;
float _pad2;
float _pad3;
};
```
### 16-Byte-Alignment
HLSL-Konstantenpuffer werden in 16-Byte-Registern (`float4`) organisiert. Ein `float4` belegt ein Register; einzelne `float`-Werte werden in 16-Byte-Blöcken zusammengefasst. Das Beispiel füllt den Puffer mit `_pad0` bis `_pad3` auf ein Vielfaches von 16 Byte auf, damit das Layout deterministisch bleibt.
### Textur- und Sampler-Bindung
- `u_input_texture` ist an `register(t0)` gebunden.
- Der Sampler `u_sampler` ist an `register(s0)` gebunden.
- Der Konstantenpuffer `hms_params` ist an `register(b0)` gebunden.
## GLSL (OpenGL, Linux x64)
Das GL-Backend (`shaders/gl/main.frag`) deklariert die Uniforms einzeln:
```glsl
#version 330 core
uniform sampler2D u_input_texture;
uniform vec2 u_resolution;
uniform float u_time_seconds;
uniform float u_delta_seconds;
uniform float u_frame_index;
uniform float u_layer_opacity;
uniform float u_audio_rms;
uniform float u_audio_peak;
uniform float u_audio_bass;
uniform float u_audio_mid;
uniform float u_audio_treble;
uniform float u_audio_beat;
uniform float param_amount;
uniform float param_radius;
uniform float param_softness;
uniform float param_roundness;
uniform float param_center_x;
uniform float param_center_y;
uniform float param_color_r;
uniform float param_color_g;
uniform float param_color_b;
uniform float param_invert;
uniform float param_mix;
in vec2 v_uv;
out vec4 fragColor;
void main()
{
vec4 src = texture(u_input_texture, v_uv);
// ...
fragColor = out_c;
}
```
## GLES (OpenGL ES 2.0, Raspberry Pi)
Das GLES-Backend (`shaders/gles/main.frag`) folgt ES-2.0-Regeln:
```glsl
#version 100
precision mediump float;
uniform sampler2D u_input_texture;
uniform vec2 u_resolution;
uniform float u_time_seconds;
uniform float u_delta_seconds;
uniform float u_frame_index;
uniform float u_layer_opacity;
uniform float u_audio_rms;
uniform float u_audio_peak;
uniform float u_audio_bass;
uniform float u_audio_mid;
uniform float u_audio_treble;
uniform float u_audio_beat;
uniform float param_amount;
uniform float param_radius;
uniform float param_softness;
uniform float param_roundness;
uniform float param_center_x;
uniform float param_center_y;
uniform float param_color_r;
uniform float param_color_g;
uniform float param_color_b;
uniform float param_invert;
uniform float param_mix;
varying vec2 v_uv;
void main()
{
vec4 src = texture2D(u_input_texture, v_uv);
// ...
gl_FragColor = out_c;
}
```
## Backend-Syntaxunterschiede
Die drei Backends müssen semantisch identische Ergebnisse liefern (PLAN.md §12.6, §15.4). Die wichtigsten Syntaxunterschiede:
| Aspekt | HLSL (D3D11) | GLSL (OpenGL) | GLES (ES 2.0) |
| --- | --- | --- | --- |
| Version | `#version` nicht nötig | `#version 330 core` | `#version 100` |
| Texturzugriff | `u_input_texture.Sample(u_sampler, uv)` | `texture(u_input_texture, v_uv)` | `texture2D(u_input_texture, v_uv)` |
| Ausgabe | `return float4(...)` an `SV_Target` | `fragColor = ...` | `gl_FragColor = ...` |
| Eingabe | `float2 uv : TEXCOORD0` | `in vec2 v_uv` | `varying vec2 v_uv` |
| Clamp | `saturate(x)` | `clamp(x, 0.0, 1.0)` | `clamp(x, 0.0, 1.0)` |
| Mischen | `lerp(a, b, t)` | `mix(a, b, t)` | `mix(a, b, t)` |
| Präzision | | | `precision mediump float;` erforderlich |
### GLES-spezifische Regeln
- **Konstante Loop-Grenzen:** GLES 2.0 erlaubt nur Schleifen mit konstanten Grenzen. Dynamische Schleifengrenzen sind nicht zulässig.
- **`texture2D` statt `texture`:** In ES 2.0 wird `texture2D` verwendet.
- **Kein `atan2`:** Die Funktion `atan2` ist in ES 2.0 nicht verfügbar; verwende `atan(y, x)` mit zwei Argumenten oder baue die Logik selbst.
- **`precision`-Deklaration:** `precision mediump float;` muss vor den Uniforms stehen.
- **`varying` statt `in`/`out`:** ES 2.0 verwendet `varying` für Vertex-zu-Fragment-Daten.
## Multipass-Regeln
Multipass-Effekte (z. B. Gaussian Blur, PLAN.md §14.3) deklarieren mehrere Pässe im Manifest:
```json
"entrypoints": {
"d3d11": {
"type": "hlsl_multipass",
"passes": [
{"pixel_shader": "shaders/d3d11/horizontal.hlsl"},
{"pixel_shader": "shaders/d3d11/vertical.hlsl"}
]
}
}
```
- Jeder Pass ist ein eigener Shader mit eigenem Dateipfad.
- Die Pässe werden in der deklarierten Reihenfolge ausgeführt; der Ausgang eines Passes ist der Eingang des nächsten.
- Jeder Pass erhält denselben Standard-Uniform-Satz.
- Die Semantik muss über alle Backends identisch sein.
## Adaptive-Quality-Varianten-Bindung
Adaptive-Quality-Varianten (PLAN.md §14.3, §15.4) können die interne Auflösung (`internal_scale`) und die Sample-Anzahl (`samples`) ändern. Die Bindung erfolgt über die deklarierten Varianten im Manifest:
```json
"adaptive_quality": {
"default": "auto",
"variants": [
{"id": "low", "internal_scale": 0.25, "samples": 5},
{"id": "medium", "internal_scale": 0.5, "samples": 9},
{"id": "high", "internal_scale": 1.0, "samples": 17}
]
}
```
Die Engine bindet die Variantenwerte an die Shader-Uniforms. Die Parameterwerte bleiben beim Wechsel der Auto-Qualitätsstufe semantisch identisch (PLAN.md §15.3). Details siehe [adaptive-quality.md](adaptive-quality.md).
## Mix-0-Bypass (§15.3)
Jeder Effekt besitzt einen `mix`-Parameter. `Mix 0` muss den Effekt kostengünstig bypassen. Das Vignette-Beispiel zeigt das Muster:
```hlsl
float m = saturate(param_mix);
if (m < 0.01)
{
return src; // Mix 0 = kostenloser Bypass (§15.3)
}
```
```glsl
float m = clamp(param_mix, 0.0, 1.0);
if (m < 0.01)
{
fragColor = src;
return;
}
```