Skip to content

feat(accessibility): Barrel Zoom for 3D shooters - #1741

Open
feilen wants to merge 3 commits into
utkarshdalal:masterfrom
feilen:feat/barrel-zoom
Open

feat(accessibility): Barrel Zoom for 3D shooters#1741
feilen wants to merge 3 commits into
utkarshdalal:masterfrom
feilen:feat/barrel-zoom

Conversation

@feilen

@feilen feilen commented Jul 19, 2026

Copy link
Copy Markdown

Description

  • Makes it more comfortable to play 3D or FPS games on a tiny screen!
  • Accessability feature which accepts strength, VFOV, and cylindrical ratio as tunables.
  • Allows for a sort of center-zoom which trends towards 'angle-area' to 'screen area' ratio being 1:1, instead of the sides of the screen taking up more space overall.
  • Hides all tunables when the feature is disabled
  • GL and Vulkan implementations

Limitations

  • Currently does not compose with other screen effects meaningfully - probably could (need to think over which effects should go in what order - e.g. FXAA should go first but FSR should go after)
  • Does not remap mouse or touch input (doesn't matter for perspective-heavy games which typically use mouse-look/controller)

Recording

out.mp4

Type of Change

  • Bug fix
  • Performance / stability improvement
  • Compatibility improvements
  • Other (requires prior approval)
    • Accessibility change

Checklist

  • If I have access to #code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.
  • This change aligns with the current project scope (core functionality, stability, or performance). If not, it has been explicitly approved beforehand.
  • I have attached a recording of the change.
  • I have read and agree to the contribution guidelines in CONTRIBUTING.md.

Summary by cubic

Add Barrel Zoom (configurable barrel distortion) to screen effects. Improves comfort for 3D/FPS on small screens by centering zoom and reducing edge stretch.

  • New Features

    • UI: toggle and sliders for Strength, VFOV, and Cylindrical Ratio; controls hidden when disabled; values persisted in ScreenEffectsConfig.
    • Rendering: GL adds BarrelDistortionEffect; Vulkan adds EFFECT_MASK_BARREL_DISTORTION, extends VulkanRenderer#setEffect(...) and JNI with barrel params; window shaders and push constants updated; color adjustments reapplied after distortion.
    • Cursor: remains correct when Barrel Zoom is enabled.
    • Defaults/ranges: Strength 0–100% (mapped 0–1), VFOV 40°–120° (via tan), Cyl Ratio 0.5–1.5; sensible defaults.
    • Caveats: limited composition with some effects (ordering TBD; e.g., FXAA before, FSR after); input mapping unchanged.
  • Dependencies

    • Switch native build to externalNativeBuild (CMake) for vulkan_renderer (arm64-v8a) with -DSKIP_WINLATOR=ON; remove prebuilt libvulkan_renderer.so to avoid duplicates.

Written for commit 8233a6f. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added an optional Barrel Zoom (Barrel Distortion) screen effect.
    • Added controls for Strength, Vertical FOV, and Cylindrical Ratio.
    • Changes apply live and are saved for future sessions.
    • Reset options restore default distortion values, with the main reset also disabling the effect.
    • Added support across OpenGL and Vulkan rendering modes, including cursor rendering.
    • Improved rendering compatibility by enabling the required native Vulkan build configuration.

@feilen
feilen requested a review from utkarshdalal as a code owner July 19, 2026 04:02
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds configurable barrel distortion to screen effects. The change updates UI controls, persisted settings, OpenGL and Vulkan rendering paths, JNI plumbing, native push constants, shaders, and native build configuration.

Changes

Barrel distortion screen effect

Layer / File(s) Summary
Configuration and screen-effects controls
app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt, app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt, app/src/main/java/app/gamenative/ui/component/dialog/ScreenEffectDialog.kt, app/src/main/res/values/strings.xml
Adds barrel distortion settings, persistence, defaults, reset behavior, localized labels, and controls across the screen-effects interfaces.
OpenGL barrel distortion implementation
app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java, app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
Adds the configurable OpenGL effect, clamps shader uniforms, computes derived height values, and applies the effect when enabled.
Vulkan effect parameter plumbing
app/src/main/java/com/winlator/renderer/VulkanRenderer.java, app/src/main/cpp/winlator/vulkan_jni.cpp, app/src/main/cpp/winlator/VulkanRendererContext.h, app/src/main/cpp/winlator/VulkanRendererContext.cpp
Extends effect APIs, JNI calls, native state, push constants, and draw-command recording with barrel distortion parameters.
Vulkan barrel distortion shader path
app/src/main/cpp/winlator/window.vert, app/src/main/cpp/winlator/window.frag
Computes barrel UV interpolants in the vertex shader and conditionally resamples the texture using them in the fragment shader.
Native build configuration
app/build.gradle.kts, app/src/main/cpp/CMakeLists.txt
Enables the app CMake build and conditionally excludes the Winlator native target when SKIP_WINLATOR is enabled.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ScreenEffectsConfig
  participant VulkanRenderer
  participant vulkan_jni
  participant VulkanRendererContext
  participant VulkanShaders
  ScreenEffectsConfig->>VulkanRenderer: Apply barrel distortion settings
  VulkanRenderer->>vulkan_jni: Pass barrel distortion parameters
  vulkan_jni->>VulkanRendererContext: Update native effect state
  VulkanRendererContext->>VulkanShaders: Upload barrel push constants
  VulkanShaders->>VulkanShaders: Compute and sample distorted UVs
Loading

Possibly related PRs

Suggested reviewers: utkarshdalal, phobos665

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely identifies the accessibility feature added for 3D shooters.
Description check ✅ Passed The description covers the change, recording, type, checklist, implementations, configuration, and known limitations.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@feilen feilen changed the title Barrel Zoom implementation feat(accessibility): Barrel Zoom for 3D shooters Jul 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt`:
- Around line 895-897: Update ScreenEffectsPanel’s resetEffects() to also set
enableBarrelDistortion to false. In the rendered Column, add the
barrel-distortion ScreenEffectToggleRow and its matching AnimatedVisibility
slider block, mirroring the implementation in GLScreenEffectsTabContent or
ScreenEffectsTabContent so users can toggle and adjust the existing
barrel-distortion state.

In `@app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt`:
- Around line 176-185: Update the barrel distortion branch in the apply logic to
retrieve the existing BarrelDistortionEffect through
composer.getEffect(BarrelDistortionEffect::class.java), falling back to a new
instance only when absent, then continue updating its strength, height, and
cylindricalRatio before adding it to effects.

In `@app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java`:
- Around line 41-46: Update BarrelDistortionEffect.onUse so the height uniform
uses the same lower-bound-only behavior as VulkanRendererContext.setEffect:
clamp height to a minimum of 0.05 without imposing an upper bound. Leave the
strength and cylindricalRatio handling unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f3da31c3-5e78-4c70-aa69-c8c5f338ef03

📥 Commits

Reviewing files that changed from the base of the PR and between c70ad6e and b3596bc.

⛔ Files ignored due to path filters (2)
  • app/src/legacy/jniLibs/arm64-v8a/libvulkan_renderer.so is excluded by !**/*.so
  • app/src/modern/jniLibs/arm64-v8a/libvulkan_renderer.so is excluded by !**/*.so
📒 Files selected for processing (11)
  • app/src/main/cpp/winlator/VulkanRendererContext.cpp
  • app/src/main/cpp/winlator/VulkanRendererContext.h
  • app/src/main/cpp/winlator/vulkan_jni.cpp
  • app/src/main/cpp/winlator/window.frag
  • app/src/main/cpp/winlator/window.vert
  • app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ScreenEffectDialog.kt
  • app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
  • app/src/main/java/com/winlator/renderer/VulkanRenderer.java
  • app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java
  • app/src/main/res/values/strings.xml

Comment thread app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
Comment thread app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 13 files

Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

Re-trigger cubic

Comment thread app/src/main/cpp/winlator/window.frag
Comment thread app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
Comment thread app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
Comment thread app/src/main/cpp/winlator/VulkanRendererContext.cpp
Comment thread app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
Comment thread app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
Comment thread app/src/main/java/com/winlator/renderer/VulkanRenderer.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt (1)

895-898: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add the barrel-distortion controls to ScreenEffectsPanel.

This panel now loads, applies, persists, and resets barrel-distortion state, but its rendered toggle list still ends at NTSC. Users therefore cannot enable or adjust barrel distortion from this entry point; mirror the toggle and adjustment block already present in the sibling screen-effects composables.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt` around
lines 895 - 898, Add the barrel-distortion toggle and adjustment controls to the
rendered control list in ScreenEffectsPanel, following the existing
implementation in the sibling screen-effects composables. Place them after the
NTSC controls and bind them to the existing barrel-distortion state, ensuring
users can enable, adjust, persist, and reset the values already handled by the
panel.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java`:
- Around line 41-42: Remove the backticks surrounding the `@Override` annotation
in BarrelDistortionEffect.onUse so it is valid Java syntax and compilation
succeeds.

---

Duplicate comments:
In `@app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt`:
- Around line 895-898: Add the barrel-distortion toggle and adjustment controls
to the rendered control list in ScreenEffectsPanel, following the existing
implementation in the sibling screen-effects composables. Place them after the
NTSC controls and bind them to the existing barrel-distortion state, ensuring
users can enable, adjust, persist, and reset the values already handled by the
panel.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 93f77d00-7ee5-4d4c-8df4-7e0b0f57ea8a

📥 Commits

Reviewing files that changed from the base of the PR and between b3596bc and 86bd0a4.

📒 Files selected for processing (3)
  • app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
  • app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
  • app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt

Comment thread app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java Outdated
feilen added 3 commits August 9, 2026 17:25
- Makes it more comfortable to play 3D or FPS games on a tiny screen!
- Accessability feature which accepts strength, VFOV, and cylindrical ratio as tunables.
- Allows for a sort of center-zoom which trends towards 'angle-area' to 'screen area' ratio being 1:1, instead of the sides of the screen
  taking up more space overall.
- Hides all tunables when the feature is disabled
- GL and Vulkan implementations

- Currently does not compose with other screen effects meaningfully - probably could (need to think over which effects should go in what
  order - e.g. FXAA should go first but FSR should go after)
- Does not remap mouse or touch input (doesn't matter for perspective-heavy games which typically use mouse-look/controller)
…istortion, align GL height clamp with Vulkan
…ke externalNativeBuild)

the app/src/main/cpp/CMakeLists.txt is now wired into the build via
externalNativeBuild in defaultConfig. cmake only builds the
vulkan_renderer target (and its adrenotools/linkernsbypass deps) for
arm64-v8a, skipping winlator and the hook targets.

the prebuilt .so files in src/legacy/jniLibs and src/modern/jniLibs
caused a duplicate with the cmake output, so they're removed.
@feilen

feilen commented Aug 10, 2026

Copy link
Copy Markdown
Author
  • Rebased
  • Addressed PR comments
  • Removed prebuild libvulkan_renderer.so and tweaked the CMakeLists.txt/build.gradle.kts to make it always spit that out (but leave libwinlator.so alone) so it's always up-to-date

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/build.gradle.kts`:
- Around line 121-127: Update the legacy and legacyXr build configuration around
externalNativeBuild so Vulkan cannot be selected for armeabi-v7a variants, or
ensure vulkan_renderer is built and packaged for that ABI. Preserve the existing
arm64-v8a Vulkan renderer configuration and align the flavor/ABI-specific
behavior with VulkanRenderer’s native library requirements.

In `@app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt`:
- Around line 481-492: Update both OpenGL and Vulkan barrel-distortion
value-text sites in ScreenEffectsPanel.kt (anchor lines 481-492 and sibling
lines 786-797) to pass an explicit Locale.US to the String.format calls for
barrelDistortionFov and barrelDistortionCylindricalRatio, preserving their
existing numeric formats.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 924a5f96-0cdc-4233-8564-1a2942d757eb

📥 Commits

Reviewing files that changed from the base of the PR and between 86bd0a4 and 8233a6f.

⛔ Files ignored due to path filters (2)
  • app/src/legacy/jniLibs/arm64-v8a/libvulkan_renderer.so is excluded by !**/*.so
  • app/src/modern/jniLibs/arm64-v8a/libvulkan_renderer.so is excluded by !**/*.so
📒 Files selected for processing (7)
  • app/build.gradle.kts
  • app/src/main/cpp/CMakeLists.txt
  • app/src/main/cpp/winlator/window.frag
  • app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
  • app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt
  • app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java
  • app/src/main/res/values/strings.xml
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/main/res/values/strings.xml
  • app/src/main/java/com/winlator/renderer/effects/BarrelDistortionEffect.java
  • app/src/main/cpp/winlator/window.frag
  • app/src/main/java/app/gamenative/ui/util/ScreenEffectsConfig.kt

Comment thread app/build.gradle.kts
Comment on lines +121 to +127
externalNativeBuild {
cmake {
targets("vulkan_renderer")
arguments.add("-DSKIP_WINLATOR=ON")
abiFilters("arm64-v8a")
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Trace Vulkan renderer loading and any ABI-specific availability checks.
rg -n -C 5 'loadLibrary\("vulkan_renderer"\)|VulkanRenderer|selectedRenderer|armeabi-v7a|abiFilters' \
  app/src/main/java app/build.gradle.kts

# Find prebuilt Vulkan renderer libraries, if any.
fd -a 'libvulkan_renderer\.so' app

Repository: utkarshdalal/GameNative

Length of output: 45002


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== App package/build configs =="
fd -a 'AndroidManifest.xml' app | while read -r f; do
  echo "--- $f"
  rg -n 'package=|android:value=".*compat|android:value=".*selectedRenderer|selectedRenderer|vulkan|surfaceflinger|useGLRenderer|XR_BUILD' "$f" || true
done

echo
echo "== selectedRenderer/Vulkan init usages with context =="
rg -n -C 8 'new XServerView|XServerView\(|selectedRenderer|useGLRenderer|VR|VulkanRenderer|loadLibrary\("vulkan_renderer"\)' \
  app/src/main/java/com/winlator/widget/XServerView.java \
  app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt \
  app/src/main/java/app/gamenative/ui/component/QuickMenu.kt \
  app/src/main/java/app/gamenative/ui/component/dialog/ScreenEffectDialog.kt \
  app/src/main/java/com/winlator/container \
  app/src/main/java/app/gamenative \
  app/src/main/java/com/winlator/renderer

echo
echo "== Render mode/container fields =="
rg -n -C 4 'rendererPresentMode|rendererMode|Vulkan|glrenderer|GLRenderer|selectedRenderer' app/src/main/java/com/winlator/container app/src/main/java/app/gamenative/ui/app || true

echo
echo "== Native library files =="
fd -a 'libvulkan_renderer\.so' .

Repository: utkarshdalal/GameNative

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Container display renderer defaults/usages =="
rg -n -C 4 'displayRenderer|useGLRenderer|useLegacyRenderer|rendererPresentMode|setDisplayRenderer|setDisplayRenderer|XServerRendererView|loadLibrary\("vulkan_renderer"\)' \
  app/src/main/java/com/winlator/container app/src/main/java/com/winlator \
  | head -n 220

echo
echo "== Container constructors/defaulting =="
fd -a 'Container.java|Container.kt|.*Container.*' app/src/main/java/com/winlator app/src/main/java/app/gamenative | while read -r f; do
  echo "--- $f"
  rg -n -C 3 'displayRenderer|useGLRenderer|useLegacyRenderer|rendererPresentMode|containerRenderer|graphicsDriver|new Container|Container\(' "$f" || true
done | head -n 240

echo
echo "== XML manifests =="
for f in $(fd -a 'AndroidManifest.xml' app); do
  echo "--- $f"
  sed -n '1,220p' "$f"
done

Repository: utkarshdalal/GameNative

Length of output: 36756


Disable Vulkan renderer on legacy armeabi-v7a variants.

The legacy and legacyXr flavors still build armeabi-v7a, while vulkan_renderer is only built for arm64-v8a and VulkanRenderer loads libvulkan_renderer.so. When container.displayRenderer is vulkan on these 32-bit builds, XServerView instantiates VulkanRenderer before loading the native library, leaving the variant without a packaged backend and making Vulkan selection unrecoverable. Disable Vulkan for armeabi-v7a legacy builds, or build vulkan_renderer for that ABI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/build.gradle.kts` around lines 121 - 127, Update the legacy and legacyXr
build configuration around externalNativeBuild so Vulkan cannot be selected for
armeabi-v7a variants, or ensure vulkan_renderer is built and packaged for that
ABI. Preserve the existing arm64-v8a Vulkan renderer configuration and align the
flavor/ABI-specific behavior with VulkanRenderer’s native library requirements.

Comment thread app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
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.

1 participant