Files
PixelplanetandCopilot 6f9a9ac6b5 feat(ui): unified spatial UI with video thumbnails and richer settings
- Add ThumbnailCache: a worker thread extracts 256x144 thumbnails and media
  metadata with FFmpeg, SBS-aware cropping, and an on-disk cache under
  ~/.cache/pixelvr/thumbs.
- Draw thumbnails on browser cards through a new rounded-corner thumb.frag
  pipeline with per-card descriptor sets.
- Redesign the browser as a sidebar + card grid, with horizontal stick
  navigation and direct shortcuts to Network/Home/Videos/Downloads/Drives.
- Expand Settings: screen curvature, UI text scale and colour, accent colour
  and UI distance, organised into sections.
- Downloads window: per-job state, progress, speed and ETA, plus pause/resume
  and cancel-active controls.
- Decoder: multi-threaded software decode and four V4L2 output buffers.
- docs: unified UI concept, redesign plan and mockups.

Release packaging is now reproducible: tools/run.sh is the shipped launcher,
tools/package-release.sh assembles the tarball, and a GitHub Actions workflow
builds it natively on ARM64 for every v* tag. Stop committing release tarballs;
they are attached to releases instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-17 09:55:48 +02:00

54 lines
1.6 KiB
GLSL

#version 450
// Textured video screen: a 16:9 screen with parametric curvature (Flat -> Curved).
// 64 horizontal segments (384 vertices) are procedurally evaluated from gl_VertexIndex.
// pc.stereo.w carries the curvature factor in [0.0, 1.0] (0 = flat, >0 = curved arc).
layout(push_constant) uniform Push {
mat4 mvp;
vec4 conversion;
vec4 range;
vec4 stereo; // x: stereoMode, y: viewIndex, z: swapEyes, w: curvature
} pc;
layout(location = 0) out vec2 vUV;
void main() {
const int kSegments = 64;
int seg = gl_VertexIndex / 6;
int vid = gl_VertexIndex % 6;
float u0 = float(seg) / float(kSegments);
float u1 = float(seg + 1) / float(kSegments);
// Quad vertex coordinates for this segment
float u = u0;
float y = 0.9;
if (vid == 1) { u = u0; y = -0.9; }
else if (vid == 2) { u = u1; y = -0.9; }
else if (vid == 3) { u = u0; y = 0.9; }
else if (vid == 4) { u = u1; y = -0.9; }
else if (vid == 5) { u = u1; y = 0.9; }
vUV = vec2(u, (0.9 - y) / 1.8);
// Nominal screen width = 3.2 (-1.6 to +1.6)
const float kWidth = 3.2;
float curv = clamp(pc.stereo.w, 0.0, 1.0);
float x = (u - 0.5) * kWidth;
float z = 0.0;
if (curv > 0.005) {
// Pure cylindrical arc of constant arc length kWidth.
// At curv=1.0, total wrap angle is ~100 degrees (1.75 rad) around the viewer.
float totalAngle = curv * 1.75;
float radius = kWidth / totalAngle;
float theta = (u - 0.5) * totalAngle;
x = radius * sin(theta);
z = radius * (1.0 - cos(theta));
}
gl_Position = pc.mvp * vec4(x, y, z, 1.0);
}