forked from community-shaders/skyrim-community-shaders
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(VR): add foveated rendering #44
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
20 commits
Select commit
Hold shift + click to select a range
dfd0b6d
feat(VR): add DlssEnhancer Bridge + Params + Pre/Postprocess (PR-3 MV…
alandtse cd96d54
feat(VR): add DlssEnhancer Core + Ops (PR-3 MVP-B)
alandtse 8966f06
feat(VR): add DlssEnhancer Modes (PR-3 MVP-B) + bot-flagged per-eye fix
alandtse e3bee66
feat(VR): add DlssEnhancerFeature + SubrectStretchCS (PR-3 MVP-B)
alandtse c10a8c5
feat(VR): wire DlssEnhancer route into Upscale + globals (PR-3 MVP-B)
alandtse b22ad87
refactor(VR): fold DlssEnhancer into Upscaling, mirror DLSSperf pattern
alandtse 911e8e3
fix(VR): correct SubrectStretchCS shader path after Upscaling refactor
alandtse 4a48a38
refactor(VR): rename DlssEnhancer -> FoveatedRender
alandtse e19e79e
fix(VR): address PR #44 review sweep
alandtse 77e1257
fix(VR): foveated route honors DLSSperf and skips in menus
alandtse e69873f
refactor(util): lift OpaquePreviewBlendCallback to Util::Subrect
alandtse 06e6a62
refactor(VR): foveated sharpening — sharpnessDLSS=0 is the single dis…
alandtse 6a4483f
feat(VR): foveated UX polish — visualizer, nasal preset, dead UI removal
alandtse f9e4656
fix(VR): foveated robustness from review feedback
alandtse 6e1061d
fix(VR): foveated review round 2 — hash, faster-fulleye, naming
alandtse 7191157
refactor(VR): foveated audit cleanup — FFX scale, trim history comments
alandtse 8aec46d
refactor(upscaling): single GetQualityModeRatio helper for all paths
alandtse e7fc690
fix(VR): foveated Faster mode HMD mask clear + UX polish
alandtse a73cdfb
fix(VR): foveated bridge contract + stretch CS init recovery
alandtse 02d1b51
fix(upscaling): GetQualityModeRatio honors DLAA (qualityMode=0)
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
There are no files selected for viewing
97 changes: 97 additions & 0 deletions
97
features/Upscaling/Shaders/Upscaling/FoveatedRender/SubrectStretchCS.hlsl
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,97 @@ | ||
| // Stretches the DRS-rendered region from a temporary render-resolution SBS texture | ||
| // to fill the entire eye in the display-resolution kMAIN SBS texture. | ||
| // Dispatched once per eye. Supports multiple sampling modes: | ||
| // 0 = Bilinear (clean upscale) | ||
| // 1 = Point / Nearest (cheapest, VRS-like broadcast) | ||
| // 2 = Gaussian Blur 3x3 (soft periphery background) | ||
|
|
||
| cbuffer StretchCB : register(b0) | ||
| { | ||
| uint DstOffsetX; // SBS destination X offset for this eye (0 or eyeWidthOut) | ||
| uint DstWidth; // display-resolution eye width | ||
| uint DstHeight; // display-resolution eye height | ||
| uint SrcOffsetX; // SBS source X offset for this eye (0 or renderEyeW) | ||
| uint SrcWidth; // render-resolution SBS total width (for UV normalisation) | ||
| uint SrcHeight; // render-resolution SBS total height | ||
| uint SrcEyeWidth; // render-resolution per-eye width | ||
| uint SrcEyeHeight; // render-resolution per-eye height | ||
| uint StretchMode; // 0=Bilinear, 1=Point, 2=GaussianBlur | ||
| float BlurRadius; // Texel-space radius for Gaussian blur (typical 0.5-4.0) | ||
| uint DebugVisualize; // 0=off, 1=tint stretched periphery red so the DLSS region pops | ||
| uint _pad; | ||
| }; | ||
|
|
||
| Texture2D<float4> SrcTex : register(t0); | ||
| SamplerState BilinearSampler : register(s0); | ||
| RWTexture2D<float4> DstTex : register(u0); | ||
|
|
||
| [numthreads(8, 8, 1)] void main(uint3 tid : SV_DispatchThreadID) { | ||
| // Zero-dim guard: a misconfigured dispatch with any zero extent would | ||
| // divide-by-zero into NaN UVs and underflow point-mode coords into | ||
| // huge uint values. Bail before any math. | ||
| if (DstWidth == 0 || DstHeight == 0 || SrcWidth == 0 || SrcHeight == 0 || | ||
| SrcEyeWidth == 0 || SrcEyeHeight == 0) | ||
| return; | ||
|
|
||
| if (tid.x >= DstWidth || tid.y >= DstHeight) | ||
| return; | ||
|
|
||
| // Map output pixel to normalised position within this eye [0,1] | ||
| float u = ((float)tid.x + 0.5) / (float)DstWidth; | ||
| float v = ((float)tid.y + 0.5) / (float)DstHeight; | ||
|
|
||
| // Map to source texel coordinates within this eye's render region | ||
| // then convert to full SBS texture UV (adding eye offset) | ||
| float srcU = (u * (float)SrcEyeWidth + (float)SrcOffsetX) / (float)SrcWidth; | ||
| float srcV = (v * (float)SrcEyeHeight) / (float)SrcHeight; | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| // Clamp sample UVs to per-eye texel bounds so the bilinear footprint and | ||
| // blur kernel can't reach across the SBS midline into the neighboring | ||
| // eye's pixels. | ||
| float2 eyeMinUV = float2(((float)SrcOffsetX + 0.5) / (float)SrcWidth, | ||
| 0.5 / (float)SrcHeight); | ||
| float2 eyeMaxUV = float2(((float)(SrcOffsetX + SrcEyeWidth) - 0.5) / (float)SrcWidth, | ||
| ((float)SrcEyeHeight - 0.5) / (float)SrcHeight); | ||
|
|
||
| float4 color; | ||
|
|
||
| if (StretchMode == 1) { | ||
| // Point / Nearest: integer texel lookup, cheapest. min() keeps us | ||
| // inside [0, SrcEyeWidth-1] / [0, SrcEyeHeight-1] when u/v == 1. | ||
| uint2 srcPixel = uint2( | ||
| min((uint)(u * (float)SrcEyeWidth), SrcEyeWidth - 1) + SrcOffsetX, | ||
| min((uint)(v * (float)SrcEyeHeight), SrcEyeHeight - 1)); | ||
| color = SrcTex.Load(int3(srcPixel, 0)); | ||
| } else if (StretchMode == 2) { | ||
| // Gaussian blur 3x3: 9-tap weighted average around center | ||
| float2 texelSize = float2(1.0 / (float)SrcWidth, 1.0 / (float)SrcHeight); | ||
| float2 center = float2(srcU, srcV); | ||
| float2 step = texelSize * BlurRadius; | ||
|
|
||
| // Gaussian weights for 3x3 kernel (sigma ~ 0.85 * radius) | ||
| // Center=4, Edge=2, Corner=1, sum=16 | ||
| float4 sum = SrcTex.SampleLevel(BilinearSampler, clamp(center, eyeMinUV, eyeMaxUV), 0) * 4.0; | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(-step.x, 0), eyeMinUV, eyeMaxUV), 0) * 2.0; | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(step.x, 0), eyeMinUV, eyeMaxUV), 0) * 2.0; | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(0, -step.y), eyeMinUV, eyeMaxUV), 0) * 2.0; | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(0, step.y), eyeMinUV, eyeMaxUV), 0) * 2.0; | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(-step.x, -step.y), eyeMinUV, eyeMaxUV), 0); | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(step.x, -step.y), eyeMinUV, eyeMaxUV), 0); | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(-step.x, step.y), eyeMinUV, eyeMaxUV), 0); | ||
| sum += SrcTex.SampleLevel(BilinearSampler, clamp(center + float2(step.x, step.y), eyeMinUV, eyeMaxUV), 0); | ||
| color = sum * (1.0 / 16.0); | ||
| } else { | ||
| // Bilinear (default): single hardware-filtered sample | ||
| color = SrcTex.SampleLevel(BilinearSampler, clamp(float2(srcU, srcV), eyeMinUV, eyeMaxUV), 0); | ||
| } | ||
|
|
||
| // Debug visualizer: tint the cheap-stretched periphery red so the DLSS | ||
| // subrect (which BlendSubrectToOutput overwrites on top of us) reads as | ||
| // the un-tinted region. Lets users see at a glance where DLSS is actually | ||
| // reconstructing vs where the cheap stretch is filling. | ||
| if (DebugVisualize != 0) { | ||
| color.rgb = lerp(color.rgb, color.rgb * float3(1.6, 0.35, 0.35), 0.6); | ||
| } | ||
|
|
||
| DstTex[uint2(tid.x + DstOffsetX, tid.y)] = color; | ||
| } | ||
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
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.