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

7.8 KiB
Raw Permalink Blame History

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:

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:

#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:

#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:

"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:

"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.

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:

float m = saturate(param_mix);
if (m < 0.01)
{
    return src; // Mix 0 = kostenloser Bypass (§15.3)
}
float m = clamp(param_mix, 0.0, 1.0);
if (m < 0.01)
{
    fragColor = src;
    return;
}