Skip to content

optional Vivecraft VR post-processing compatibility (fix: https://github.com/FoundryMC/Veil/issues/91 )#143

Open
DarkFoxYT wants to merge 10 commits into
FoundryMC:1.21from
DarkFoxYT:vivecraft-vr-compat
Open

optional Vivecraft VR post-processing compatibility (fix: https://github.com/FoundryMC/Veil/issues/91 )#143
DarkFoxYT wants to merge 10 commits into
FoundryMC:1.21from
DarkFoxYT:vivecraft-vr-compat

Conversation

@DarkFoxYT
Copy link
Copy Markdown
Contributor

Optional Vivecraft VR Post-Processing Compatibility

Overview

This PR introduces an optional VeilVRCompat integration layer that enables VR-aware post-processing when running alongside Vivecraft, while fully preserving Veil’s existing rendering pipeline for standard desktop gameplay.

The integration is entirely reflective, meaning Veil does not require a hard Vivecraft dependency. VR-specific behavior only activates during active Vivecraft stereo eye rendering (LEFT / RIGHT render passes). Outside of VR rendering, Veil continues using its normal framebuffer, post-processing, and dynamic buffer workflow unchanged.

vr

Key Features

VR-Aware Rendering Path

  • Detects Vivecraft reflectively without introducing a compile-time dependency.
  • Detects active VR rendering state and the currently rendered eye.
  • Routes veil:post through isolated left/right eye post-processing framebuffers.
  • Creates per-eye variants of data-driven Veil framebuffers used by post pipelines.
  • Keeps temporary composite framebuffers and dynamic buffers isolated per eye.
  • Automatically resizes VR dynamic buffers to the active eye render target instead of the desktop window size.

Per-Eye Lighting & Buffer Isolation

  • Routes Veil light rendering and built-in bloom capture through eye-specific framebuffers.
  • Resolves Vivecraft eye render targets reflectively to avoid binding the desktop mirror target during VR rendering.
  • Prevents cross-eye contamination for:
    • color
    • depth
    • normals
    • material masks
    • light buffers
    • velocity/history buffers

This avoids stereo mismatches, ghosting, reprojection issues, and other VR rendering artifacts.

VR-Safe Rendering State Handling

  • Temporarily disables Vivecraft hidden-area stencil/scissor state during Veil light and post passes, then restores it afterward.
  • Avoids clearing the main Vivecraft render target during stereo eye rendering when doing so could break Vivecraft compositing alpha.
vr2

Automatic VR Uniform Support

Post shaders automatically receive VR-aware uniforms:

  • VeilIsVR
  • VeilEyeIndex
  • VeilViewMatrix
  • VeilProjectionMatrix
  • VeilInverseViewMatrix
  • VeilInverseProjectionMatrix
  • VeilCameraPosition
  • VeilViewportSize

Additional VR safety uniforms/fallbacks are also provided for:

  • motion blur
  • camera shake
  • fullscreen distortion scaling

Why Per-Eye Rendering Matters

Vivecraft renders the scene independently for each eye. Sharing framebuffer data between eyes can introduce severe stereo artifacts, including:

  • ghosting
  • stereo desync
  • broken reprojection
  • incorrect depth-based effects
  • motion discomfort / nausea

This integration isolates eye-specific rendering resources while preserving the existing Veil shader authoring workflow. Existing shaders continue to function normally and automatically receive the correct eye-specific framebuffer state, matrices, viewport data, and camera information without requiring separate shader variants.


Non-VR Behavior

The VR compatibility layer remains completely dormant unless all of the following conditions are true:

  • Vivecraft is installed
  • VR compatibility is enabled in Veil
  • Vivecraft reports VR rendering as active
  • The current render pass is LEFT or RIGHT

When those conditions are not met:

  • Veil uses the normal framebuffer manager path.
  • Composite post-processing uses the existing shared temporary framebuffer map.
  • Dynamic buffers use the standard render path.
  • Post shaders continue receiving the normal camera and viewport uniforms.

Configuration

New client configuration options added to config/veil-client.json:

  • enableVrCompatibility
  • usePerEyePostProcessing
  • disableMotionBlurInVR
  • reduceDistortionInVR
  • vrPostQuality
  • debugVREyeBuffers

VR-Specific Adjustments

Default VR Safety Behavior

  • Motion blur is disabled by default in VR.
  • Camera shake intensity is reduced/suppressed.
  • Strong fullscreen distortion effects are scaled down.

Per-Eye Resource Isolation

The following systems are isolated per eye during stereo rendering:

  • temporal framebuffer history
  • dynamic color/depth/normal/material/light buffers
  • velocity buffers
  • bloom mip/blur chains
  • composite post-processing intermediates

Dynamic Buffer Improvements

  • Dynamic albedo/normal buffers used by Veil lighting now bind directly to the active eye render target.
  • Buffers resize to the active eye resolution, preventing lower-left boxed rendering artifacts common in VR framebuffer mismatches.

Lighting Compatibility

  • Veil lighting passes render independently from Vivecraft’s hidden-area eye stencil, preventing partial-eye clipping and cutout artifacts.
vr3

Limitations

  • Veil cannot automatically guarantee that every externally created framebuffer is VR-safe. Warnings are logged when post passes reference framebuffers that are not known to be per-eye isolated.
  • Custom shaders using non-standard motion blur, distortion, or camera-shake uniforms may need to adopt the new Veil*Scale VR safety uniforms.
  • Vivecraft integration remains fully reflective and intentionally avoids a hard dependency.
  • This implementation targets Fabric 1.21.1 with Yarn mappings and should still be validated in real headset testing scenarios.

ps: i just wanted to have veil have vr support for horror mod lol but if it ain't gona be used i hope ya don't mind if i use this version for myself, but i tested and it works for fabric and neoforge so like yeah... also according to this it would be peak so like i made it XD #91

DarkFox and others added 5 commits May 21, 2026 01:37
This branch keeps the light changes focused on buffer correctness and instance upload cost. It does not change the voxel shadow grid or the point/area light fragment shaders.

## ImGuiMC Renderer Fix

- Updated ImGuiMC to `1.2.4`.
- Added Fabric and NeoForge compatibility mixins for `foundry.imgui.impl.renderer.v0.ImGuiRendererGL33`.
- Fixed ImGuiMC 1.2.x shader compilation on NVIDIA/OpenGL 3.3 by replacing the invalid GLSL 130 version line that included the `core` profile suffix.
- This prevents ImGui from failing to compile its vertex/fragment shaders during startup.

## Sodium 0.8.12 Compatibility

- Updated the Sodium dependency to `0.8.12-alpha.3+mc1.21.1`.
- Adjusted Fabric and NeoForge Sodium compat to use Sodium's current `RenderSectionManager` rebuild scheduling path.

## Light Instance Buffer Optimization

- Added a lightweight revision counter to `LightData`.
- Point and area light setters now mark their light data dirty when position, color, brightness, size, radius, angle, distance, orientation, or occlusion changes.
- `InstancedLightRenderer` now tracks the previous visible-light order and each light's uploaded revision.
- If the visible light order changes, or the GL instance buffer is resized, Veil still uploads the full visible light buffer.
- If the visible light order is unchanged, only lights whose data revision changed are uploaded with `glBufferSubData`.
- This keeps the current rendering model intact while avoiding full instance-buffer uploads for static lights.

## Indirect Sphere Compute Shader Fix

- Fixed NVIDIA GLSL compile errors in `veil:light/indirect_sphere`.
- `gl_GlobalInvocationID` is unsigned, while Veil's light buffer offsets and command buffer indexes are signed integers.
- The shader now converts the invocation ID math once and uses `int` for buffer indexing, avoiding implicit `int` to `uint` casts that NVIDIA rejects.
@KalarianAthecila
Copy link
Copy Markdown
Contributor

I like this one, hyped for them to merge this!

- Added an optional Vivecraft bridge that detects Vivecraft reflectively and only activates during Vivecraft left/right eye passes.
- Kept normal non-VR Veil rendering on the existing path.
- Added per-eye post, dynamic, bloom, light, and temporary composite framebuffer isolation.
- Cached per-eye VR framebuffers and dynamic wrappers so they are reused until the eye target size changes.
- Added performance-oriented VR quality caps for post, bloom, and light buffers, while keeping bloom visible for first-person held items in VR and normal desktop rendering.
- Resolved post/light work against Vivecraft's active eye target instead of assuming the vanilla main framebuffer owns the headset image.
- Added Sodium/Iris/Embeddium detection logs and a config-controlled Sodium-compatible Vivecraft eye-target fallback.
- Added configurable VR debug counters for frame time, post time, framebuffer resize/create counts, blit/copy counts, and fallback usage.
- Added optional CSV frame-time history output for VR profiling.

### Why VR needs this

Vivecraft renders left and right eyes as separate camera passes. Sharing color, depth, normals, light buffers, velocity, or temporal history across eyes causes stereo mismatch, screen-stuck lighting, cutouts, and nausea-inducing artifacts. The compatibility path keeps shader authoring unchanged by feeding existing Veil shaders per-eye framebuffers, matrices, camera position, and viewport size.

### Performance and compatibility notes

- VR buffers are rebuilt only when the active eye size changes.
- `optimizeVrPerformance` caps VR post, bloom, and light-buffer scales to reduce headset pixel cost; users can disable it for higher quality captures.
- Per-eye dynamic framebuffer wrappers are pooled to avoid allocation/free churn during eye switches.
- Vivecraft VR initialized/active state is cached per render frame to avoid repeated reflective checks from every post stage.
- Veil light dynamic buffers stay warm while lights exist in the world, avoiding shader/buffer churn when visible lights briefly leave the frustum.
- Voxel shadow-grid setup is skipped for DDA light passes that do not have occlusion-enabled lights.
- Isolated auto-clear framebuffers are cleared only if used that frame.
- Post resolves are counted and routed to the active Vivecraft eye target.
- Frame-time logs report last/average/min/max frame milliseconds plus estimated FPS when `debugVRPerformance` is enabled.
- Sodium/Embeddium fallback behavior is optional and logged once when used.
- First-person bloom capture uses the first-person depth target before compositing back into the normal main target, so held items can glow without being clipped by world depth.

### Testing

- Launch without Vivecraft and confirm normal post-processing behavior is unchanged.
- Launch with Vivecraft installed but VR inactive and confirm the VR path stays dormant.
- Launch in Vivecraft VR with and without Sodium, enable `debugVRPerformance`, and verify left/right buffer creation stops after the initial eye-size setup.
- Test Veil lights, bloom, first-person bloom, temporal effects, and GUI/world compositing.
@DarkFoxYT
Copy link
Copy Markdown
Contributor Author

DarkFoxYT commented May 22, 2026

so uhh latest commit is just for like better performance and compat with bloom and stuff in fp and in vr and having other stuff like sodium not crash when vr is active.

Small changes but mainly just issue fixing XD fixes this too btw #107

@DarkFoxYT
Copy link
Copy Markdown
Contributor Author

oh btw i wanna slide in a quick note, the fps is capped due to the refresh rate of the headset, vivecraft does that by it'self and it is completeley normal, just saying!

DarkFox and others added 2 commits May 24, 2026 03:13
The issue was that Veil always skipped Minecraft’s vanilla particles_target setup in Fabulous mode, even when Veil dynamic buffers were not actually active. Particles then rendered into the wrong target and disappeared during Fabulous compositing. I changed it so vanilla target setup/clear runs unless Veil is truly replacing that framebuffer state. I also corrected the clear hook to wrap clearRenderState() instead of accidentally wrapping setup twice.
@DarkFoxYT
Copy link
Copy Markdown
Contributor Author

quick fix for issue #144

The issue was that Veil always skipped Minecraft’s vanilla particles_target setup in Fabulous mode, even when Veil dynamic buffers were not actually active. Particles then rendered into the wrong target and disappeared during Fabulous compositing. I changed it so vanilla target setup/clear runs unless Veil is truly replacing that framebuffer state. I also corrected the clear hook to wrap clearRenderState() instead of accidentally wrapping setup twice.

@Derpgamer22
Copy link
Copy Markdown

Can't wait for a possible fix for the Fabulous graphics issue so I can finally see particles behind colored glass 🥹

Comment thread common/src/main/java/foundry/veil/api/compat/VeilVRCompat.java Outdated
@DarkFoxYT
Copy link
Copy Markdown
Contributor Author

DarkFoxYT commented May 25, 2026

Updated the optional Vivecraft VR compatibility work with a cleaner, lower-noise debug path and improved documentation.

Changes:

  • Added a concise console status line for Vivecraft/VR state:
    • whether Vivecraft is present
    • whether VR initialized
    • whether VR is active
    • detected provider/runtime/hardware when available
  • Removed duplicate VR matrix/camera uniforms from the post shader upload path.
    • Shaders should use the existing VeilCamera buffer instead.
    • This avoids duplicating data already exposed as VeilCamera.ViewMat, VeilCamera.ProjMat, VeilCamera.IViewMat, VeilCamera.IProjMat, and VeilCamera.CameraPosition.
  • Removed the shader compatibility warning/check to avoid noisy or misleading logs.
  • Polished the VR shader compatibility wiki with a clearer compatibility checklist.
  • Kept the VR integration optional and reflective.

Validation:

  • :common:compileJava
  • :fabric:compileJava
  • :neoforge:compileJava

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants