Files
Toastconcern--FrameStudio/layer/env_ps.frag
T
ToastconcernandClaude Opus 5.5 f7345a5ac3 Frame Studio and Frame Home: cross-platform builds
Frame Studio now builds for Windows (x64, x86, ARM64), Linux (x64, x86, ARM64)
and macOS (Apple Silicon, Intel):
- studio/platform.h with Win32 and POSIX implementations (dialogs through
  tinyfiledialogs on Linux/macOS), a GLFW window beside the Win32 one, and a
  platform-neutral frame pacer
- MoltenVK support in the renderer (portability enumeration) and bundled in
  the macOS app
- 32-bit builds: large-address-aware, LZMA packing within a 32-bit address space
- unaligned file reads in the loaders go through loadUnaligned (no UB)
- scripts/build-studio.sh, studio/build_windows.bat [x64|x86|arm64],
  cmake/llvm-mingw.cmake, and a GitHub Actions workflow building every target

Frame Home installs without Studio: frame/install-frame-home.{sh,ps1} and
"Install Frame Home.bat" (packaged as FrameHome-installer.zip).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 12:03:25 -05:00

44 lines
2.2 KiB
GLSL

#version 450
// Frame Home's environment, drawn by vrcompositor in place of Aurora (frame_home_layer.cpp swaps it in for every
// Aurora pipeline: same vertex shader, same set 0, plus set 1 below).
//
// Aurora's vertex shader hands over each point's tracking-space position (location 1) and the frame's uniform block
// holds the eye position (_m11, as Aurora's floor shader reads it). The direction from the eye to the point is
// looked up in the newest frame Frame Home published: its projection * view rotation for that eye, so the picture
// stays locked to the world as the head turns between Frame Home's frame and the compositor's (rotation reprojection).
// SteamVR's per-frame block (set 0, binding 4), as far as the members used here.
layout(set = 0, binding = 4, std140) uniform CompositorFrame {
layout(row_major) mat4 m0, m1, m2, m3, m4;
vec4 m5[4];
vec4 m6; // w: the environment's opacity (the compositor dims it behind the menu and in transitions)
vec4 m7;
vec2 m8, m9;
vec4 m10;
vec4 m11; // xyz: this eye's position, tracking space
} frame;
layout(set = 1, binding = 0) uniform sampler2DArray home; // both eyes, layer 0 left, 1 right
layout(set = 1, binding = 1, std140) uniform HomeFrame {
mat4 viewProj[2]; // projection * view rotation, per eye (tracking space)
vec4 eyePos[2]; // where each eye was when Frame Home rendered it
vec4 params; // x: brightness (0 fades to black), y: 1 when there's something to show
} homeFrame;
layout(location = 1) in vec3 worldPos;
layout(location = 0) out vec4 color;
void main() {
const vec3 eye = frame.m11.xyz;
const vec3 dir = normalize(worldPos - eye);
const int k = distance(eye, homeFrame.eyePos[0].xyz) <= distance(eye, homeFrame.eyePos[1].xyz) ? 0 : 1;
const vec4 c = homeFrame.viewProj[k] * vec4(dir, 0.0);
vec3 rgb = vec3(0.0);
if (c.w > 1e-5 && homeFrame.params.y > 0.5) {
const vec2 uv = (c.xy / c.w) * 0.5 + 0.5;
// (explicit level 0: subsampled frames must be read so, and plain ones have only that level)
rgb = textureLod(home, vec3(uv, float(k)), 0.0).rgb;
}
color = vec4(rgb * homeFrame.params.x, frame.m6.w);
}