Phase 0: Repository-Initialisierung nach Bauplan v1.2
- Struktur gemäß §8 (Eigentumsgrenzen), PLAN.md als normative Basis - Pflichtdokumente: STATUS.md, ERRORS.md, TEST_REPORT.md, CHANGELOG.md, ADRs - ADR-0001 Python 3.13-Pin, ADR-0002 GStreamer 1.28.6-Pin (Windows), ADR-0003 IPC TCP+MessagePack v1 - Kernpakete: hms_protocol, hms_domain, hms_parameter, hms_artnet, hms_adaptive, hms_capabilities, hms_plugin_sdk - Renderer-Spike: D3D11-Primärpfad + Dev-GL-Pfad (§36 Nr. 4-5) - Control Core: FastAPI REST + WebSocket (§36 Nr. 9) - Beispielplugins: Passthrough + Gaussian Blur (3 Adaptive-Quality- Varianten, HLSL/GLSL/GLES) - Tools: Art-Net-Emulator, Fixture-Generator (Master32/Layer64-CSV), Capability-Probe - JSON-Schemas: IPC, Plugin, Projekt, Cluster - 121 Unit-/Integrationstests grün, Ruff grün Gate 0 bleibt offen: Hardwaremessungen nur auf echter Windows-Referenz- hardware gültig (§29.7, §33).
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
# Example Passthrough (SDK-Referenz)
|
||||
|
||||
Erstes Beispielplugin gemäß PLAN.md §14 und §36 Nr. 6: HLSL-Passthrough mit einem live änderbaren Parameter `mix` sowie semantisch gleiche GLSL- und GLES-Testvarianten.
|
||||
|
||||
- `shaders/d3d11/passthrough.hlsl` – Windows-Primärpfad (D3D11, PS_5_0)
|
||||
- `shaders/gl/passthrough.frag` – Linux x64 (GLSL 330)
|
||||
- `shaders/gles/passthrough.frag` – Raspberry Pi / GLES (100)
|
||||
|
||||
Alle Varianten verwenden dieselben semantischen Standard-Inputs (§14.4).
|
||||
Das Plugin validiert fehlerfrei gegen `hms_plugin_sdk` (Validator-Test in `tests/unit/test_plugin_manifest.py`).
|
||||
|
||||
Shader-Kompilierung und Bildgleichheit werden auf Zielsystemen geprüft
|
||||
(Gate-0-Hardwaremessung, §29.3); dieser Container besitzt keine GPU.
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "com.hms.fx.example_passthrough",
|
||||
"name": "Example Passthrough",
|
||||
"version": "1.0.0",
|
||||
"api_version": 1,
|
||||
"kind": "filter",
|
||||
"vendor": "HMS",
|
||||
"entrypoints": {
|
||||
"d3d11": {
|
||||
"type": "hlsl_singlepass",
|
||||
"passes": [
|
||||
{"pixel_shader": "shaders/d3d11/passthrough.hlsl"}
|
||||
]
|
||||
},
|
||||
"gl": {
|
||||
"type": "glsl_singlepass",
|
||||
"passes": [
|
||||
{"fragment": "shaders/gl/passthrough.frag"}
|
||||
]
|
||||
},
|
||||
"gles": {
|
||||
"type": "glsl_es_singlepass",
|
||||
"passes": [
|
||||
{"fragment": "shaders/gles/passthrough.frag"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"capabilities": {
|
||||
"minimum_tier": "PI_LITE",
|
||||
"requires_input_texture": true,
|
||||
"supported_backends": ["d3d11", "gl", "gles"]
|
||||
},
|
||||
"adaptive_quality": {
|
||||
"default": "auto",
|
||||
"variants": [
|
||||
{"id": "low", "internal_scale": 1.0, "samples": 1},
|
||||
{"id": "medium", "internal_scale": 1.0, "samples": 1},
|
||||
{"id": "high", "internal_scale": 1.0, "samples": 1}
|
||||
],
|
||||
"transition_ms": 180,
|
||||
"semantic_parameters_unchanged": ["mix"]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"id": "mix",
|
||||
"label": "Mix",
|
||||
"type": "float",
|
||||
"minimum": 0.0,
|
||||
"maximum": 1.0,
|
||||
"default": 0.0,
|
||||
"dmx_slots": [1],
|
||||
"curve": "linear"
|
||||
}
|
||||
],
|
||||
"failure_mode": "bypass"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// HMS MediaEngine – Beispielplugin: Passthrough mit Live-Parameter "mix"
|
||||
// PLAN.md §14.4 (Standard-Shaderinputs), §36 Nr. 6
|
||||
// D3D11-Pixelshader (PS_5_0); Bindung übernimmt der Backend-Adapter (ADR-0004 offen).
|
||||
// Projekte referenzieren niemals konkrete Backend-Variablennamen (§12.6).
|
||||
|
||||
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_mix; // Plugin-Parameter, live änderbar (0..1)
|
||||
float _pad0; // 16-Byte-Alignment des cbuffer
|
||||
};
|
||||
|
||||
float4 mainPS(float4 pos : SV_POSITION, float2 uv : TEXCOORD0) : SV_Target
|
||||
{
|
||||
float4 src = u_input_texture.Sample(u_sampler, uv);
|
||||
|
||||
// Live-Parameter: mix blendet zwischen Original und zeitmodulierter Helligkeit
|
||||
float pulse = 0.5 + 0.5 * sin(u_time_seconds * 2.0);
|
||||
float m = saturate(param_mix);
|
||||
float3 rgb = src.rgb * lerp(1.0, pulse, m);
|
||||
float a = src.a * u_layer_opacity;
|
||||
|
||||
return float4(rgb * u_layer_opacity, a);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#version 330 core
|
||||
// HMS MediaEngine – Beispielplugin: Passthrough mit Live-Parameter "mix"
|
||||
// GLSL-Testvariante, semantisch identisch zur HLSL-Implementierung (§36 Nr. 6).
|
||||
// Standard-Inputs gemäß PLAN.md §14.4; Bindung über den GL-Backend-Adapter.
|
||||
|
||||
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_mix;
|
||||
|
||||
in vec2 v_uv;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 src = texture(u_input_texture, v_uv);
|
||||
|
||||
float pulse = 0.5 + 0.5 * sin(u_time_seconds * 2.0);
|
||||
float m = clamp(param_mix, 0.0, 1.0);
|
||||
vec3 rgb = src.rgb * mix(1.0, pulse, m);
|
||||
float a = src.a * u_layer_opacity;
|
||||
|
||||
fragColor = vec4(rgb * u_layer_opacity, a);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#version 100
|
||||
// HMS MediaEngine – Beispielplugin: Passthrough (OpenGL ES, Raspberry Pi Pfad)
|
||||
// Semantisch identisch zu HLSL/GLSL-Varianten (§36 Nr. 6, §12.6).
|
||||
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_mix;
|
||||
|
||||
varying vec2 v_uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 src = texture2D(u_input_texture, v_uv);
|
||||
|
||||
float pulse = 0.5 + 0.5 * sin(u_time_seconds * 2.0);
|
||||
float m = clamp(param_mix, 0.0, 1.0);
|
||||
vec3 rgb = src.rgb * mix(1.0, pulse, m);
|
||||
float a = src.a * u_layer_opacity;
|
||||
|
||||
gl_FragColor = vec4(rgb * u_layer_opacity, a);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Gaussian Blur (SDK-Beispiel, PLAN.md §14.3 / §15.2 / §36 Nr. 10)
|
||||
|
||||
Separierbarer Gauß-Blur mit zwei Pässen (horizontal + vertikal) je Backend.
|
||||
|
||||
Adaptive Quality: drei deklarierte Varianten (low/medium/high), die sich nur
|
||||
in `internal_scale` und `samples` unterscheiden; `radius` bleibt semantisch
|
||||
unverändert (§5.2). Radius 0 bypassed kostenfrei (§15.3).
|
||||
|
||||
| Variante | internal_scale | samples |
|
||||
| --- | --- | --- |
|
||||
| low | 0.25 | 5 |
|
||||
| medium | 0.5 | 9 |
|
||||
| high | 1.0 | 17 |
|
||||
|
||||
Alle Varianten müssen vor Aktivierung kompiliert werden (§5.2, §33);
|
||||
Bild- und Performance-Abnahme erfolgt auf Zielsystemen (§15.4).
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "com.hms.fx.gaussian_blur",
|
||||
"name": "Gaussian Blur",
|
||||
"version": "1.0.0",
|
||||
"api_version": 1,
|
||||
"kind": "filter",
|
||||
"vendor": "HMS",
|
||||
"entrypoints": {
|
||||
"d3d11": {
|
||||
"type": "hlsl_multipass",
|
||||
"passes": [
|
||||
{"pixel_shader": "shaders/d3d11/horizontal.hlsl"},
|
||||
{"pixel_shader": "shaders/d3d11/vertical.hlsl"}
|
||||
]
|
||||
},
|
||||
"gl": {
|
||||
"type": "glsl_multipass",
|
||||
"passes": [
|
||||
{"fragment": "shaders/gl/horizontal.frag"},
|
||||
{"fragment": "shaders/gl/vertical.frag"}
|
||||
]
|
||||
},
|
||||
"gles": {
|
||||
"type": "glsl_es_multipass",
|
||||
"passes": [
|
||||
{"fragment": "shaders/gles/horizontal.frag"},
|
||||
{"fragment": "shaders/gles/vertical.frag"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"capabilities": {
|
||||
"minimum_tier": "DESKTOP_LITE",
|
||||
"requires_input_texture": true,
|
||||
"supported_backends": ["d3d11", "gl", "gles"]
|
||||
},
|
||||
"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}
|
||||
],
|
||||
"transition_ms": 180,
|
||||
"semantic_parameters_unchanged": ["radius"]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"id": "radius",
|
||||
"label": "Radius",
|
||||
"type": "float",
|
||||
"minimum": 0.0,
|
||||
"maximum": 40.0,
|
||||
"default": 0.0,
|
||||
"dmx_slots": [1],
|
||||
"curve": "quadratic"
|
||||
},
|
||||
{
|
||||
"id": "quality",
|
||||
"label": "Quality",
|
||||
"type": "enum",
|
||||
"values": ["auto", "low", "medium", "high"],
|
||||
"default": "auto",
|
||||
"dmx_slots": [2]
|
||||
}
|
||||
],
|
||||
"failure_mode": "bypass"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// HMS MediaEngine – Gaussian Blur, horizontaler Pass (separable)
|
||||
// PLAN.md §14.3-Beispiel, §36 Nr. 10: drei Adaptive-Quality-Varianten
|
||||
// (low: 5 Samples, medium: 9, high: 17) werden vorab kompiliert; nur
|
||||
// u_quality_samples/internal_scale ändern sich, param_radius bleibt semantisch identisch.
|
||||
|
||||
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_radius; // 0..40 (quadratic curve, DMX P1)
|
||||
float u_quality_samples; // 5 | 9 | 17 je Variante (Backend-Bindung)
|
||||
float _pad0;
|
||||
float _pad1;
|
||||
};
|
||||
|
||||
float4 mainPS(float4 pos : SV_POSITION, float2 uv : TEXCOORD0) : SV_Target
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
float4 src = u_input_texture.Sample(u_sampler, uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
return src; // Radius 0 = kostenloser Bypass (§15.3)
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
float2 texel = float2(1.0, 0.0) / u_resolution.xy;
|
||||
|
||||
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
|
||||
float total = 0.0;
|
||||
[loop]
|
||||
for (float i = 0.0; i < samples; i += 1.0)
|
||||
{
|
||||
float t = i - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += u_input_texture.Sample(u_sampler, uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
return acc / total;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// HMS MediaEngine – Gaussian Blur, vertikaler Pass (separable)
|
||||
// Identisch zu horizontal.hlsl mit texel = (0, 1).
|
||||
|
||||
Texture2D u_input_texture : register(t0);
|
||||
SamplerState u_sampler : register(s0);
|
||||
|
||||
cbuffer hms_params : register(b0)
|
||||
{
|
||||
float4 u_resolution;
|
||||
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_radius;
|
||||
float u_quality_samples;
|
||||
float _pad0;
|
||||
float _pad1;
|
||||
};
|
||||
|
||||
float4 mainPS(float4 pos : SV_POSITION, float2 uv : TEXCOORD0) : SV_Target
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
float4 src = u_input_texture.Sample(u_sampler, uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
float2 texel = float2(0.0, 1.0) / u_resolution.xy;
|
||||
|
||||
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
|
||||
float total = 0.0;
|
||||
[loop]
|
||||
for (float i = 0.0; i < samples; i += 1.0)
|
||||
{
|
||||
float t = i - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += u_input_texture.Sample(u_sampler, uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
return acc / total;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#version 330 core
|
||||
// HMS MediaEngine – Gaussian Blur, horizontaler Pass (GLSL, Linux x64)
|
||||
// Semantik identisch zur HLSL-Variante (§12.6, §15.4).
|
||||
|
||||
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_radius;
|
||||
uniform float u_quality_samples;
|
||||
|
||||
in vec2 v_uv;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
vec4 src = texture(u_input_texture, v_uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
fragColor = src;
|
||||
return;
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
vec2 texel = vec2(1.0, 0.0) / u_resolution;
|
||||
|
||||
vec4 acc = vec4(0.0);
|
||||
float total = 0.0;
|
||||
for (float i = 0.0; i < samples; i += 1.0)
|
||||
{
|
||||
float t = i - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += texture(u_input_texture, v_uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
fragColor = acc / total;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#version 330 core
|
||||
// HMS MediaEngine – Gaussian Blur, vertikaler Pass (GLSL, Linux x64)
|
||||
|
||||
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_radius;
|
||||
uniform float u_quality_samples;
|
||||
|
||||
in vec2 v_uv;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
vec4 src = texture(u_input_texture, v_uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
fragColor = src;
|
||||
return;
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
vec2 texel = vec2(0.0, 1.0) / u_resolution;
|
||||
|
||||
vec4 acc = vec4(0.0);
|
||||
float total = 0.0;
|
||||
for (float i = 0.0; i < samples; i += 1.0)
|
||||
{
|
||||
float t = i - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += texture(u_input_texture, v_uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
fragColor = acc / total;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#version 100
|
||||
// HMS MediaEngine – Gaussian Blur, horizontaler Pass (GLES, Raspberry Pi)
|
||||
// ES 2.0: Schleifen mit konstanter Höchstgrenze; Abbruch über Bedingung.
|
||||
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_radius;
|
||||
uniform float u_quality_samples;
|
||||
|
||||
varying vec2 v_uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
vec4 src = texture2D(u_input_texture, v_uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
gl_FragColor = src;
|
||||
return;
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
vec2 texel = vec2(1.0, 0.0) / u_resolution;
|
||||
|
||||
vec4 acc = vec4(0.0);
|
||||
float total = 0.0;
|
||||
for (int i = 0; i < 17; i++)
|
||||
{
|
||||
if (float(i) >= samples) { break; }
|
||||
float t = float(i) - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += texture2D(u_input_texture, v_uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
gl_FragColor = acc / total;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#version 100
|
||||
// HMS MediaEngine – Gaussian Blur, vertikaler Pass (GLES, Raspberry Pi)
|
||||
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_radius;
|
||||
uniform float u_quality_samples;
|
||||
|
||||
varying vec2 v_uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
float radius = max(param_radius, 0.0);
|
||||
vec4 src = texture2D(u_input_texture, v_uv);
|
||||
if (radius < 0.01)
|
||||
{
|
||||
gl_FragColor = src;
|
||||
return;
|
||||
}
|
||||
|
||||
float samples = clamp(u_quality_samples, 1.0, 17.0);
|
||||
float stepSize = radius / max(samples - 1.0, 1.0);
|
||||
vec2 texel = vec2(0.0, 1.0) / u_resolution;
|
||||
|
||||
vec4 acc = vec4(0.0);
|
||||
float total = 0.0;
|
||||
for (int i = 0; i < 17; i++)
|
||||
{
|
||||
if (float(i) >= samples) { break; }
|
||||
float t = float(i) - (samples - 1.0) * 0.5;
|
||||
float w = exp(-(t * t) / (samples * 0.5));
|
||||
acc += texture2D(u_input_texture, v_uv + texel * (t * stepSize)) * w;
|
||||
total += w;
|
||||
}
|
||||
gl_FragColor = acc / total;
|
||||
}
|
||||
Reference in New Issue
Block a user