forked from community-shaders/skyrim-community-shaders
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(vr): foveated SSR raymarching #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
15d176c
feat(vr): foveated SSR raymarching
alandtse ca588b3
refactor(vr): use kFullCoverageThreshold for foveation full-eye check
alandtse e68c174
refactor(vr): derive foveation profile from both eyes; clarify covera…
alandtse 1ce96da
refactor(vr): rename foveation coverageArea to coverageScale
alandtse 0e3df6f
refactor(vr): make FoveationProfile.available match clamped coverage
alandtse d6b7ddf
chore(state): assert 16-byte alignment of SharedData foveation fields
alandtse de4f54b
docs(vr): trim verbose foveation comments
alandtse ab7b658
perf(vr): specialize power-4 foveation mask; fix coverage comment
alandtse 94fca5c
docs(vr): cap foveation comments at 1-2 lines
alandtse 7efffc4
docs(vr): compress FoveatedCommon header to 2 lines
alandtse File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| #ifndef FOVEATED_MASK_HLSLI | ||
| #define FOVEATED_MASK_HLSLI | ||
|
|
||
| // Superellipse (shape power 4 = squircle) foveation mask: a smooth center->periphery weight that | ||
| // avoids the hard seam of a rect mask. CPU mirror of the clamping is in src/Features/FoveatedCommon.h. | ||
|
|
||
| #ifndef FOVEATED_CENTER_SCALE_MIN | ||
| # define FOVEATED_CENTER_SCALE_MIN 0.25 | ||
| #endif | ||
| #ifndef FOVEATED_CENTER_SCALE_MAX | ||
| # define FOVEATED_CENTER_SCALE_MAX 1.0 | ||
| #endif | ||
| #ifndef FOVEATED_CENTER_FEATHER_MIN | ||
| # define FOVEATED_CENTER_FEATHER_MIN 1e-4 | ||
| #endif | ||
| #ifndef FOVEATED_CENTER_HORIZONTAL_SCALE_MIN | ||
| # define FOVEATED_CENTER_HORIZONTAL_SCALE_MIN 1.0 | ||
| #endif | ||
| #ifndef FOVEATED_CENTER_HORIZONTAL_SCALE_MAX | ||
| # define FOVEATED_CENTER_HORIZONTAL_SCALE_MAX 2.0 | ||
| #endif | ||
| #ifndef FOVEATED_MASK_SHAPE_POWER | ||
| # define FOVEATED_MASK_SHAPE_POWER 4 | ||
| #endif | ||
|
|
||
| float FoveatedClampCenterScale(float centerScale) | ||
| { | ||
| return clamp(centerScale, FOVEATED_CENTER_SCALE_MIN, FOVEATED_CENTER_SCALE_MAX); | ||
| } | ||
|
|
||
| float2 FoveatedComputeCenterUV(float2 centerOffset) | ||
| { | ||
| return clamp(float2(0.5, 0.5) + centerOffset, float2(0.0, 0.0), float2(1.0, 1.0)); | ||
| } | ||
|
|
||
| float FoveatedClampCenterHorizontalScale(float centerHorizontalScale) | ||
| { | ||
| return clamp(centerHorizontalScale, FOVEATED_CENTER_HORIZONTAL_SCALE_MIN, FOVEATED_CENTER_HORIZONTAL_SCALE_MAX); | ||
| } | ||
|
|
||
| float2 FoveatedComputeMaskRadii(float centerScale, float centerHorizontalScale) | ||
| { | ||
| float clampedCenterScale = FoveatedClampCenterScale(centerScale); | ||
| float clampedCenterHorizontalScale = FoveatedClampCenterHorizontalScale(centerHorizontalScale); | ||
| float2 radii = float2(clampedCenterScale * clampedCenterHorizontalScale * 0.5, clampedCenterScale * 0.5); | ||
| return max(radii, FOVEATED_CENTER_FEATHER_MIN.xx); | ||
| } | ||
|
|
||
| float FoveatedComputeNormalizedFeather(float centerScale, float centerFeather, float centerHorizontalScale) | ||
| { | ||
| float2 radii = FoveatedComputeMaskRadii(centerScale, centerHorizontalScale); | ||
| float baseRadius = max(min(radii.x, radii.y), FOVEATED_CENTER_FEATHER_MIN); | ||
| return max(centerFeather, FOVEATED_CENTER_FEATHER_MIN) / baseRadius; | ||
| } | ||
|
|
||
| float FoveatedComputeMaskDistance(float2 eyeUv, float centerScale, float centerHorizontalScale, float2 centerOffset) | ||
| { | ||
| float2 radii = FoveatedComputeMaskRadii(centerScale, centerHorizontalScale); | ||
| float2 centerUv = FoveatedComputeCenterUV(centerOffset); | ||
| float2 normalized = (eyeUv - centerUv) / radii; | ||
| float2 absoluteNormalized = abs(normalized); | ||
| #if FOVEATED_MASK_SHAPE_POWER == 4 | ||
| // Squircle fast path: pow(t,4) == (t*t)^2 and pow(sum,1/4) == sqrt(sqrt(sum)), | ||
| // so the default shape avoids three transcendental pow() calls per pixel in | ||
| // the SSR path that is explicitly trying to save GPU time. | ||
| float2 sq = absoluteNormalized * absoluteNormalized; | ||
| float pNorm = sq.x * sq.x + sq.y * sq.y; | ||
| return sqrt(sqrt(max(pNorm, 0.0))); | ||
| #else | ||
| float shapePower = max((float)FOVEATED_MASK_SHAPE_POWER, 1.0); | ||
| float invShapePower = 1.0 / shapePower; | ||
| float pNorm = pow(absoluteNormalized.x, shapePower) + pow(absoluteNormalized.y, shapePower); | ||
| return pow(max(pNorm, 0.0), invShapePower); | ||
| #endif | ||
| } | ||
|
|
||
| float FoveatedComputeCenterBlendWeight(float2 eyeUv, float centerScale, float centerFeather, float centerHorizontalScale, float2 centerOffset) | ||
| { | ||
| float normalizedFeather = FoveatedComputeNormalizedFeather(centerScale, centerFeather, centerHorizontalScale); | ||
| float maskDistance = FoveatedComputeMaskDistance(eyeUv, centerScale, centerHorizontalScale, centerOffset); | ||
| return 1.0 - smoothstep(1.0, 1.0 + normalizedFeather, maskDistance); | ||
| } | ||
|
|
||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #ifndef FOVEATED_SHADER_DETAIL_HLSLI | ||
| #define FOVEATED_SHADER_DETAIL_HLSLI | ||
|
|
||
| // Per-pixel detail weight for foveated effects: pass the mode (0=off/1=feathered/2=hard, see | ||
| // FoveatedCommon::GetShaderMode) + mask params, get a 0..1 weight (0 outside the mask = skip). | ||
|
|
||
| #include "Common/FoveatedMask.hlsli" | ||
|
|
||
| static const float FOVEATED_SHADER_DETAIL_MODE_FEATHERED = 1.0; | ||
| static const float FOVEATED_SHADER_DETAIL_MODE_HARD_CUTOFF = 2.0; | ||
|
|
||
| float FoveatedEvaluateShaderDetailWeight(float mode, float2 eyeUv, float centerScale, float centerFeather, float centerHorizontalScale, float2 centerOffset) | ||
| { | ||
| bool detailModeEnabled = mode >= FOVEATED_SHADER_DETAIL_MODE_FEATHERED; | ||
| if (!detailModeEnabled) | ||
| return 1.0f; | ||
|
|
||
| bool hardCutoffMode = mode >= FOVEATED_SHADER_DETAIL_MODE_HARD_CUTOFF; | ||
| if (hardCutoffMode) { | ||
| float edgeDistance = FoveatedComputeMaskDistance(eyeUv, centerScale, centerHorizontalScale, centerOffset); | ||
| return edgeDistance > 1.0f ? 0.0f : 1.0f; | ||
| } | ||
|
|
||
| return FoveatedComputeCenterBlendWeight(eyeUv, centerScale, centerFeather, centerHorizontalScale, centerOffset); | ||
| } | ||
|
|
||
| bool FoveatedIsShaderDetailActive(float detailWeight) | ||
| { | ||
| return detailWeight > 0.0001f; | ||
| } | ||
|
|
||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| #pragma once | ||
|
|
||
| #include <algorithm> | ||
| #include <cmath> | ||
|
|
||
| // Shared CPU-side helpers for VR foveated shader detail; GPU mirror in FoveatedMask.hlsli, with | ||
| // GetShaderMode's 0/1/2 encoding as the contract. Only SSR-consumed pieces exist (compute helpers omitted). | ||
| namespace FoveatedCommon | ||
| { | ||
| constexpr float kCenterScaleMin = 0.25f; | ||
| constexpr float kCenterScaleMax = 1.0f; | ||
| constexpr float kCenterFeather = 0.05f; | ||
| constexpr float kCenterHorizontalScaleMin = 1.0f; | ||
| constexpr float kCenterHorizontalScaleMax = 2.0f; | ||
| constexpr float kFullCoverageThreshold = 0.999f; | ||
|
|
||
| enum class DetailMode | ||
| { | ||
| Off, | ||
| Feathered, | ||
| HardCutoff | ||
| }; | ||
|
|
||
| constexpr DetailMode GetDetailMode(bool a_enabled, bool a_hardCutoff) | ||
| { | ||
| if (!a_enabled) | ||
| return DetailMode::Off; | ||
| return a_hardCutoff ? DetailMode::HardCutoff : DetailMode::Feathered; | ||
| } | ||
|
|
||
| // 0 = off, 1 = feathered, 2 = hard cutoff. Must match the | ||
| // FOVEATED_SHADER_DETAIL_MODE_* constants in FoveatedShaderDetail.hlsli. | ||
| constexpr float GetShaderMode(DetailMode a_mode) | ||
| { | ||
| switch (a_mode) { | ||
| case DetailMode::Feathered: | ||
| return 1.0f; | ||
| case DetailMode::HardCutoff: | ||
| return 2.0f; | ||
| case DetailMode::Off: | ||
| default: | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| inline float ClampCenterScale(float a_value) | ||
| { | ||
| if (!std::isfinite(a_value)) | ||
| return kCenterScaleMax; | ||
| return std::clamp(a_value, kCenterScaleMin, kCenterScaleMax); | ||
| } | ||
|
|
||
| // A near-full center means foveation does nothing useful — callers skip the | ||
| // per-pixel mask in that case to avoid paying its cost for no saving. | ||
| inline bool IsActiveCoverage(float a_centerScale) | ||
| { | ||
| return ClampCenterScale(a_centerScale) < kFullCoverageThreshold; | ||
| } | ||
|
|
||
| inline float ClampCenterHorizontalScale(float a_value) | ||
| { | ||
| if (!std::isfinite(a_value)) | ||
| return 1.0f; | ||
| return std::clamp(a_value, kCenterHorizontalScaleMin, kCenterHorizontalScaleMax); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.