mirror of
https://github.com/Toastconcern/FrameStudio.git
synced 2026-10-28 16:02:39 +01:00
Frame Studio - Gaussian splats (PLY, SPZ v2-v4), PLY vertex colours, panorama skies - Copy, cut, paste and duplicate for objects, splats and world items - Walkable-area rebake moved off the UI thread; viewport one frame sooner; refresh-locked pacing (FS_PACE=timer for the old one) - Fixed: bundle thumbnail use-after-free crash, auto-save deleting environments, saves into scratch copies, edits lost on non-ASCII paths, unopenable manifests with inf/nan, bundle save data loss, opening a home marking it changed, gizmo NaN, long paths, many malformed-file crashes - Updater verifies sha256, journals the swap and never leaves the exe missing Frame Home - Seats turn you to face their way - Draw batching (Hand Tutorials up to ~20% less GPU time), cut-out EQUAL pass, late head-pose read before submit - Proper queue-family hand-over to the compositor layer; layer descriptor generations and seqlocked slots; structural SPIR-V check - Fixed: hangs/crashes on damaged .fenv files and shaders, render-pass validation error, sync hazard in the foveation smoothing pass, unverified update downloads, half-done installs Tests: tests_loco/env_share/spv_check wired into CMake (FRAME_TESTS) and CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VsaXGU27gsrXjDoFtyFJP9
52 lines
2.9 KiB
GLSL
52 lines
2.9 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).
|
|
// A frame shown again (half rate, or the next one late) is carried on by how the rig was moving (env_share.h Motion):
|
|
// its smooth turn exactly, its walking as if everything were walk.w metres away.
|
|
|
|
// 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
|
|
vec4 turn; // xy: cos, sin of the rig's turn since the frame (about tracking-space up)
|
|
vec4 walk; // xyz: the rig's walk since the frame (frame's tracking space, m), w: depth taken (0: none)
|
|
} homeFrame;
|
|
|
|
layout(location = 1) in vec3 worldPos;
|
|
layout(location = 0) out vec4 color;
|
|
|
|
void main() {
|
|
const vec3 eye = frame.m11.xyz;
|
|
vec3 dir = normalize(worldPos - eye);
|
|
const int k = distance(eye, homeFrame.eyePos[0].xyz) <= distance(eye, homeFrame.eyePos[1].xyz) ? 0 : 1;
|
|
// Into the frame's tracking space: the rig turned since by this much (about the head), and walked.
|
|
const vec2 cs = homeFrame.turn.xy;
|
|
dir = vec3(cs.x * dir.x + cs.y * dir.z, dir.y, -cs.y * dir.x + cs.x * dir.z);
|
|
if (homeFrame.walk.w > 0.0) dir = normalize(dir * homeFrame.walk.w + homeFrame.walk.xyz);
|
|
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);
|
|
}
|