Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ namespace ExtendedMaterials
float2 GetParallaxCoords(float distance, float2 coords, float mipLevel, float3 viewDir, float3x3 tbn, float noise, Texture2D<float4> tex, SamplerState texSampler, uint channel, DisplacementParams params, out float pixelOffset)
#endif
{
pixelOffset = 0.5;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
float3 viewDirTS = normalize(mul(tbn, viewDir));
#if defined(LANDSCAPE)
viewDirTS.xy /= viewDirTS.z * 0.7 + 0.3 + params[0].FlattenAmount; // Fix for objects at extreme viewing angles
Expand Down Expand Up @@ -496,7 +497,7 @@ namespace ExtendedMaterials
#endif
nearBlendToFar *= nearBlendToFar;
float offset = (1.0 - parallaxAmount) * -maxHeight + minHeight;
pixelOffset = lerp(parallaxAmount * scale, 0, nearBlendToFar);
pixelOffset = saturate(lerp(parallaxAmount, 0.5, nearBlendToFar));
return lerp(viewDirTS.xy * offset + coords.xy, coords, nearBlendToFar);
}

Expand All @@ -509,7 +510,7 @@ namespace ExtendedMaterials
weights[5] = input.LandBlendWeights2.y;
#endif

pixelOffset = 0;
pixelOffset = 0.5;
return coords;
}

Expand Down
47 changes: 40 additions & 7 deletions features/Upscaling/Shaders/Upscaling/ClearHMDMaskCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,53 @@
// depth == 0.0 is the unrendered/hidden area value (Skyrim reversed-Z: far plane = 0).
// DepthIn is the combined stereo depth buffer; DepthOffsetX selects the eye's half.
// ColorInOut is the isolated per-eye buffer; ColorOffsetX is always 0.
//
// When DepthWidth > 0, coordinate scaling is enabled: depth is at render-res while
// color is at display-res. The shader maps display-res color coordinates to render-res
// depth coordinates for the mask lookup.
//
// FallbackIn (t1): when bound, masked pixels read from this texture instead of writing
// black. When unbound, D3D11 returns (0,0,0,0) — same as clearing to black.
// FallbackOffsetX selects the eye's half in the stereo fallback texture.

cbuffer ClearHMDMaskCB : register(b0)
{
uint DepthOffsetX; // X offset into combined stereo depth (0 = left, eyeWidth = right)
uint ColorOffsetX; // X offset into color target (always 0 for per-eye buffers)
uint pad0;
uint pad1;
uint DepthOffsetX; // X offset into combined stereo depth (0 = left, eyeWidth = right)
uint ColorOffsetX; // X offset into color target (always 0 for per-eye buffers)
uint DepthOffsetY; // Y offset into combined stereo depth (non-zero when viewport scaling crops vertically)
uint FallbackOffsetX; // X offset into FallbackIn for stereo (0 when unused or left eye)
// Optional coordinate scaling (zero = disabled, for backwards compat)
uint DepthWidth; // render-res eye width; if 0, no scaling (1:1 depth/color coords)
uint DepthHeight; // render-res eye height
uint ColorWidth; // display-res eye width
uint ColorHeight; // display-res eye height
};

Texture2D<float> DepthIn : register(t0);
Texture2D<float4> FallbackIn : register(t1);
RWTexture2D<float4> ColorInOut : register(u0);

[numthreads(8, 8, 1)] void main(uint3 dispatchID : SV_DispatchThreadID) {
// Read from stereo depth, write to potentially stereo color
if (DepthIn[dispatchID.xy + uint2(DepthOffsetX, 0)] == 0.0)
ColorInOut[dispatchID.xy + uint2(ColorOffsetX, 0)] = float4(0.0, 0.0, 0.0, 0.0);
uint w, h;
ColorInOut.GetDimensions(w, h);
if (dispatchID.x >= w || dispatchID.y >= h)
return;

uint2 colorPos = dispatchID.xy + uint2(ColorOffsetX, 0);
uint2 depthPos;

if (DepthWidth > 0) {
// Scale from display-res color coordinates to render-res depth coordinates
depthPos = uint2(
(dispatchID.x * DepthWidth) / ColorWidth,
(dispatchID.y * DepthHeight) / ColorHeight) +
uint2(DepthOffsetX, DepthOffsetY);
} else {
depthPos = dispatchID.xy + uint2(DepthOffsetX, DepthOffsetY);
}

if (DepthIn[depthPos] == 0.0)
ColorInOut[colorPos] = FallbackIn[dispatchID.xy + uint2(FallbackOffsetX, 0)];
// When FallbackIn is unbound (existing callers): returns (0,0,0,0) → clears to black
Comment thread
coderabbitai[bot] marked this conversation as resolved.
// When FallbackIn is bound (TAA mask restore): returns display RT content
}
48 changes: 48 additions & 0 deletions features/Upscaling/Shaders/Upscaling/DLSSCompositePS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Format-converting fullscreen pixel shader with optional bilinear upscale.
// Used by TAAReorder to composite between textures of different DXGI formats
// (e.g. R8G8B8A8_UNORM conductor RTs <-> R11G11B10_FLOAT kMAIN).
// The GPU's output merger handles format conversion automatically.
//
// BILINEAR_UPSCALE variant: upscales render-res content to display-res by
// mapping output pixel positions through the dynamic resolution scale,
// like PureDark's dynamicResScale in his blend shader.

#include "Upscaling/UpscaleVS.hlsl"

#ifdef PSHADER

Texture2D<float4> Source : register(t0);

# ifdef BILINEAR_UPSCALE

cbuffer CompositeCB : register(b0)
{
float2 DynResScale; // renderRes / displayRes (per-eye)
float2 EyeOffset; // (i * eyeWidth, 0) in texels
float2 SrcTexSize; // full texture dimensions in texels
float2 pad;
};

SamplerState LinearSampler : register(s0);

float4 main(VS_OUTPUT input) : SV_Target
{
// Map display-res pixel position to render-res source position.
// Subtract eye offset, scale to render-res, add eye offset back.
float2 localPos = input.Position.xy - EyeOffset;
float2 srcLocal = localPos * DynResScale;
float2 srcPos = srcLocal + EyeOffset;
float2 srcUV = srcPos / SrcTexSize;
return Source.SampleLevel(LinearSampler, srcUV, 0);
}

# else

float4 main(VS_OUTPUT input) : SV_Target
{
return Source.Load(int3(input.Position.xy, 0));
}

# endif // BILINEAR_UPSCALE

#endif // PSHADER
70 changes: 70 additions & 0 deletions features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @file DepthUpscalePS.hlsl
* @brief Point-sampled depth buffer upscaling for VR depth-based culling
*
* When upscaling (FSR/DLSS) is active, the depth buffer is rendered at a lower
* resolution than the display. Skyrim VR's depth-based culling (OBBOcclusionTesting)
* reads from the depth buffer to determine object visibility, but with a mismatched
* resolution, objects may be incorrectly culled (appearing to flicker in/out of view).
*
* This shader upscales the low-resolution depth buffer to full resolution using
* pure point sampling. Previous conservative blending (GatherRed + lerp toward
* min depth) caused HAM mask bleed: depth == 0 values from the hidden area mesh
* leaked into valid depth through the 2x2 neighborhood blend, creating artifacts
* at the mask boundary after DRS upscaling.
*
* Based on depth upscaling approach by vrnord
* https://github.com/vrnord/skyrim-community-shaders-VR-DLSS
*/

#include "Upscaling/UpscaleVS.hlsl"

#if defined(PSHADER)
# include "Common/FrameBuffer.hlsli"
# include "Common/SharedData.hlsli"

typedef VS_OUTPUT PS_INPUT;

struct PS_OUTPUT
{
float Depth: SV_Depth;
};

Texture2D<float> DepthLowRes : register(t0);

cbuffer DepthUpscaleCB : register(b0)
{
float2 SourceDim; // Full texture dimensions (texels)
float2 InvSourceDim; // 1.0 / SourceDim
float2 Scale; // resolutionScale (render/display ratio)
float2 Pad;
};

/**
* @brief Main pixel shader entry point
*
* Pure point-sampled depth upscaling. Maps display-res pixel position to
* render-res texel and loads directly — no blending, no mask bleed.
*/
PS_OUTPUT main(PS_INPUT input)
{
PS_OUTPUT psout;

// Map full-res UV to render-res UV (same transform as the engine's
// GetDynamicResolutionAdjustedScreenPosition).
float2 uv = Scale * input.TexCoord;

// Per-eye clamping for SBS stereo: prevent sampling across the center seam.
bool isRight = input.TexCoord.x >= 0.5;
float halfScale = 0.5 * Scale.x;
uv.x = clamp(uv.x, isRight ? halfScale : 0.0, isRight ? Scale.x : halfScale);
uv.y = clamp(uv.y, 0.0, Scale.y);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Nearest texel coordinate — pure point sampling, no blending
int2 texel = int2(floor(uv * SourceDim));
psout.Depth = DepthLowRes.Load(int3(texel, 0));

return psout;
}

#endif
41 changes: 41 additions & 0 deletions features/Upscaling/Shaders/Upscaling/FeatheredCompositeCS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
cbuffer FeatherCB : register(b0)
{
uint CropX; // paste position X in output space
uint CropY; // paste position Y in output space
uint CropW; // crop width
uint CropH; // crop height
float FeatherWidth; // feather distance in pixels (inward from crop edge)
float3 pad;
};

Texture2D<float4> CropTexture : register(t0); // DLSS output (crop-sized, at {0,0})
RWTexture2D<float4> OutputTexture : register(u0); // vrFinalOutput (already filled with periphery)

[numthreads(8, 8, 1)] void main(uint3 dispatchID : SV_DispatchThreadID) {
// dispatchID is in crop-local space (0..CropW-1, 0..CropH-1)
int2 cropLocal = int2(dispatchID.xy);
if (cropLocal.x >= (int)CropW || cropLocal.y >= (int)CropH)
return;

// Output pixel = crop-local + paste offset
int2 pixel = cropLocal + int2(CropX, CropY);

// Distance from nearest crop edge (positive = inside)
float distLeft = (float)cropLocal.x;
float distRight = (float)(CropW - 1 - cropLocal.x);
float distTop = (float)cropLocal.y;
float distBottom = (float)(CropH - 1 - cropLocal.y);
float distFromEdge = min(min(distLeft, distRight), min(distTop, distBottom));
Comment on lines +24 to +28
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Mar 23, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Edge distance calculation differs from pixel shader variant.

This compute shader uses CropW - 1 - cropLocal.x for the right edge distance, while FeatheredCompositePS.hlsl uses (CropOrigin.x + CropSize.x) - pixelPos.x. The CS version produces distances offset by 1 pixel at the right/bottom edges, which may cause a subtle visual discontinuity if both shaders are used in the same pipeline.

🔧 Suggested fix for consistency
 	// Distance from nearest crop edge (positive = inside)
 	float distLeft = (float)cropLocal.x;
-	float distRight = (float)(CropW - 1 - cropLocal.x);
+	float distRight = (float)(CropW - cropLocal.x);
 	float distTop = (float)cropLocal.y;
-	float distBottom = (float)(CropH - 1 - cropLocal.y);
+	float distBottom = (float)(CropH - cropLocal.y);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
float distLeft = (float)cropLocal.x;
float distRight = (float)(CropW - 1 - cropLocal.x);
float distTop = (float)cropLocal.y;
float distBottom = (float)(CropH - 1 - cropLocal.y);
float distFromEdge = min(min(distLeft, distRight), min(distTop, distBottom));
float distLeft = (float)cropLocal.x;
float distRight = (float)(CropW - cropLocal.x);
float distTop = (float)cropLocal.y;
float distBottom = (float)(CropH - cropLocal.y);
float distFromEdge = min(min(distLeft, distRight), min(distTop, distBottom));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@features/Upscaling/Shaders/Upscaling/FeatheredCompositeCS.hlsl` around lines
24 - 28, The compute shader's right/bottom edge distances (distRight,
distBottom) use "- 1" and thus are off by one compared to the pixel shader
variant; update the calculations in FeatheredCompositeCS.hlsl so distRight =
(float)(CropW - cropLocal.x) and distBottom = (float)(CropH - cropLocal.y)
(keeping distLeft/distTop and distFromEdge as-is) to match the pixel shader
logic (which uses (CropOrigin + CropSize) - pixelPos).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

leaving open. Feathered Edge is still being worked on.

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.

@vrnord, understood — acknowledged. The off-by-one consistency check between FeatheredCompositeCS.hlsl and FeatheredCompositePS.hlsl can be revisited once the feathered edge implementation stabilises. Good luck with the ongoing work on it!

(ノ◕ヮ◕)ノ*:・゚✧


🧠 Learnings used
Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 2003
File: features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl:55-61
Timestamp: 2026-03-24T04:30:29.538Z
Learning: In `features/Upscaling/Shaders/Upscaling/DepthUpscalePS.hlsl` (doodlum/skyrim-community-shaders PR `#2003`), the shader is dispatched per-eye using per-eye dimensions (DstWidth/DstHeight). The UV (`input.TexCoord`) is derived from `dispatchID / DstDim`, which is already eye-local — not full SBS/packed stereo coordinates. The per-eye UV clamping logic (isRight, halfScale) operates entirely in eye-local space, and there is no stereo seam issue. Do not flag SBS seam concerns for this shader.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 2003
File: package/Shaders/VRStereoOptimizations/StencilCS.hlsl:97-108
Timestamp: 2026-03-24T04:37:14.725Z
Learning: In `package/Shaders/VRStereoOptimizations/StencilCS.hlsl` (doodlum/skyrim-community-shaders PR `#2003`), `EdgeWidth` is present in `VRStereoOptParams` cbuffer (`cbuffers.hlsli`) as a future-tuning placeholder but is intentionally NOT wired into `maxWidth` in the classification loop — `maxWidth` is hardcoded to `kInnerWidth = 2`. Do not flag this as a bug or suggest `maxWidth = max(kInnerWidth, EdgeWidth)`; the wiring is deferred to a later PR.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: package/Shaders/Lighting.hlsl:3089-3095
Timestamp: 2026-03-16T13:13:11.490Z
Learning: In `package/Shaders/Lighting.hlsl` (doodlum/skyrim-community-shaders), the `TREE_ANIM` alpha test path intentionally uses a hardcoded `0.1` floor check (`if (alpha < 0.1) discard;`) and `AlphaTestRefRS` rather than `SharedData::VRAlphaTestThreshold`. `VRAlphaTestThreshold` is wired into `DistantTree.hlsl` and `RunGrass.hlsl` only. The threshold wiring for `Lighting.hlsl`'s `TREE_ANIM` path is deferred to a separate VR foliage PR.

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 1947
File: package/Shaders/DeferredCompositeCS.hlsl:234-243
Timestamp: 2026-03-14T08:35:42.651Z
Learning: In `package/Shaders/DeferredCompositeCS.hlsl` (doodlum/skyrim-community-shaders), the fallback non-IBL SKYLIGHTING specular path intentionally double-weights with `skylightingSpecular`: `dalcScaled` is computed as `IrradianceToGamma(IrradianceToLinear(directionalAmbientColorSpecular) * skylightingSpecular)`, and the final `finalIrradiance` is then `lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular)`. This is original engine logic preserved from before PR `#1947` and should not be flagged as a double-attenuation bug.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1966
File: package/Shaders/ISVolumetricLightingGenerateCS.hlsl:0-0
Timestamp: 2026-03-11T08:05:10.801Z
Learning: In doodlum/skyrim-community-shaders, the `sqrt()` applied to `CloudShadows::GetCloudShadowMult()` in `package/Shaders/ISVolumetricLightingGenerateCS.hlsl` is intentional. The maintainer (Dlizzio) confirmed it is used to increase cloud shadow strength at harsh angles for volumetric lighting, and should not be removed or replaced with a direct linear multiply.

Learnt from: vrnord
Repo: doodlum/skyrim-community-shaders PR: 1982
File: src/Features/VR/StereoBlend.cpp:98-109
Timestamp: 2026-03-16T13:13:31.383Z
Learning: In `src/Features/VR/StereoBlend.cpp` (doodlum/skyrim-community-shaders), debug modes 4/5 ("Overwrite", "Overwrite Eye1") in the `StereoBlendDebugMode` selector are NOT separate shader variants. They use the same `stereoBlendOverwriteCS` shader with different cbuffer parameters. When `vrStereoOptActive` is true, `stereoBlendOverwriteCS` is always selected unconditionally and `StereoBlendDebugMode` values 4/5 do not map to any distinct code path.

Learnt from: CR
Repo: doodlum/skyrim-community-shaders PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-25T04:43:36.075Z
Learning: Applies to src/Features/**/*.{h,hpp,cpp,hlsl} : Consider GPU workload and performance impact when implementing graphics features, with special attention to shader compilation and runtime performance

Learnt from: CR
Repo: doodlum/skyrim-community-shaders PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-25T04:43:36.075Z
Learning: Applies to features/**/Shaders/**/*.{hlsl,fxh} : Add shader files for graphics features to the `features/YourFeature/Shaders/` directory and use shader compilation templates for deployment

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 1947
File: features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli:107-115
Timestamp: 2026-03-14T08:35:02.326Z
Learning: In `features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli`, the pattern of scaling `directionalAmbientColorSpecular` by `skylightingSpecular` (via `dalcScaled`) before the final `lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular)` is intentional pre-existing behavior preserved from the original implementation. Do not flag this as double-attenuation; the combined attenuation is by design.

Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-08-03T18:37:19.690Z
Learning: ISReflectionsRayTracing.hlsl and ISWorldMap.hlsl in the skyrim-community-shaders repository are image-space post-processing shaders that perform color sampling and blending operations that need proper linear color space handling for the linear lighting system. ISReflectionsRayTracing handles screen-space reflections and should use conditional Color::IrradianceToLinear/Gamma conversions similar to ISCompositeLensFlareVolumetricLighting.hlsl. ISWorldMap performs 7x7 color accumulation that should be done in linear space similar to the pattern used in ISSAOComposite.hlsl.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1271-1274
Timestamp: 2026-03-22T18:40:47.322Z
Learning: Repo: doodlum/skyrim-community-shaders — Maintainer preference (PR `#2000` on 2026-03-22): In src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI, keep `resetLayout = false;` at the end of the frame (after PaletteWindow::Draw). The reset is intentionally one-shot for windows rendered that frame; closed windows are allowed to reopen with their previous geometry. Do not move the clear later or broadcast resets to closed windows.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 2000
File: src/WeatherEditor/EditorWindow.cpp:1239-1244
Timestamp: 2026-03-22T18:32:16.698Z
Learning: In doodlum/skyrim-community-shaders (PR `#2000`, 2026-03-22), maintainer preference: keep the default browser width logic in src/WeatherEditor/EditorWindow.cpp within EditorWindow::RenderUI — browserWidth = min(availableWidth * 0.5f, 960.0f * Util::GetUIScale()) is applied unconditionally (before checking settings.showViewport) to preserve a consistent left-rail width on first-use/reset. Do not change this to fill full width when the viewport is hidden.

Learnt from: Dlizzio
Repo: doodlum/skyrim-community-shaders PR: 1950
File: package/Shaders/Lighting.hlsl:2008-2012
Timestamp: 2026-03-07T00:53:21.267Z
Learning: In doodlum/skyrim-community-shaders PR `#1950`, the maintainer (Dlizzio) confirmed that per-axis normal reorientation for triplanar-projected normals/detail in package/Shaders/Lighting.hlsl is not required for their use case; the current approach intentionally mixes samples without axis-specific swizzle/sign correction.

Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 1880
File: src/Features/VR/InSceneOverlay.cpp:603-604
Timestamp: 2026-02-15T08:13:49.292Z
Learning: The skyrim-community-shaders repository uses OpenVR SDK version 1.0.10, where IVRCompositor::Submit is at vtable index 5 (0-based). Do not suggest changing this to index 6, as that is only correct for newer OpenVR versions (2.x).

Learnt from: CR
Repo: doodlum/skyrim-community-shaders PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-25T04:43:36.075Z
Learning: Applies to src/**/*.{h,hpp,cpp} : Ensure code changes work across SE/AE/VR Skyrim variants using runtime detection and `REL::RelocateMember()` patterns for compatibility


float4 dlss = CropTexture.Load(int3(cropLocal, 0));

if (FeatherWidth <= 0.0 || distFromEdge >= FeatherWidth) {
// Inside crop interior or no feathering: 100% DLSS
OutputTexture[pixel] = dlss;
} else {
// Feather zone: smooth blend from periphery (TAA-stabilized) to DLSS
float blend = smoothstep(0.0, FeatherWidth, distFromEdge);
float4 periphery = OutputTexture[pixel];
OutputTexture[pixel] = lerp(periphery, dlss, blend);
}
}
56 changes: 56 additions & 0 deletions features/Upscaling/Shaders/Upscaling/FeatheredCompositePS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Feathered DLSS crop composite using hardware alpha blending.
// Based on PureDark's approach from Skyrim-Upscaler VR (MIT license).
//
// The render target already contains TAA'd periphery content.
// We output float4(DLSSColor, featherAlpha) and let the output merger's
// SrcAlpha/InvSrcAlpha blend preserve the periphery in the feather zone
// and outside the crop rect entirely.

#include "Upscaling/UpscaleVS.hlsl"

#ifdef PSHADER

Texture2D<float4> CropTexture : register(t0);
SamplerState LinearSampler : register(s0);

cbuffer FeatheredCompositeCB : register(b0)
{
float2 CropOrigin; // paste position (x, y) in output-eye pixel coords
float2 CropSize; // crop width, height in pixels
float FeatherWidth; // feather distance in pixels (inward from crop edge)
float _pad0;
float2 SrcUVOrigin; // UV origin in source texture for this crop region
float2 SrcUVScale; // UV scale: maps [0,1] crop-local UV to source texture UV range
};
Comment thread
vrnord marked this conversation as resolved.

float4 main(VS_OUTPUT input) : SV_Target
{
float2 pixelPos = input.Position.xy;

// Distance from each edge of the crop rect (positive = inside)
float distLeft = pixelPos.x - CropOrigin.x;
float distRight = (CropOrigin.x + CropSize.x) - pixelPos.x;
float distTop = pixelPos.y - CropOrigin.y;
float distBottom = (CropOrigin.y + CropSize.y) - pixelPos.y;

float minDist = min(min(distLeft, distRight), min(distTop, distBottom));

// Outside crop rect: fully transparent (hardware blend preserves TAA'd periphery)
if (minDist <= 0.0)
return float4(0, 0, 0, 0);

// Feather alpha: smoothstep ramp from 0 at edge to 1 at FeatherWidth inside
// (matches the smoothstep from the original CS for visual consistency)
float alpha = (FeatherWidth > 0.0) ? smoothstep(0.0, FeatherWidth, minDist) : 1.0;

// Map pixel position to crop-local UV [0,1], then remap to source texture UV.
// For per-eye textures: SrcUVOrigin=(0,0), SrcUVScale=(1,1) (identity).
// For SBS textures: SrcUVOrigin/Scale select the correct eye's crop region.
float2 cropUV = (pixelPos - CropOrigin) / CropSize;
float2 srcUV = cropUV * SrcUVScale + SrcUVOrigin;
float3 dlssColor = CropTexture.SampleLevel(LinearSampler, srcUV, 0).rgb;

return float4(dlssColor, alpha);
}

#endif // PSHADER
17 changes: 17 additions & 0 deletions features/Upscaling/Shaders/Upscaling/ForceAlphaCS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Forces alpha to 1.0 across the entire texture.
// Used after DLSS center paste onto submit texture to ensure Scaleform UI renders.
// DLSS output may have alpha=0 (from R11G11B10→R8G8B8A8 conversion with no alpha source),
// which can prevent UI compositing in the DLSS center area.

RWTexture2D<float4> ColorInOut : register(u0);

[numthreads(8, 8, 1)] void main(uint3 dispatchID : SV_DispatchThreadID) {
uint w, h;
ColorInOut.GetDimensions(w, h);
if (dispatchID.x >= w || dispatchID.y >= h)
return;

float4 c = ColorInOut[dispatchID.xy];
c.a = 1.0;
ColorInOut[dispatchID.xy] = c;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
24 changes: 24 additions & 0 deletions features/Upscaling/Shaders/Upscaling/VRPeripheryFillCS.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Bilinear upscale from render-resolution per-eye buffer to display-resolution per-eye buffer.
// Used for VR viewport scaling: fills the full eye output with a cheap upscale so the
// periphery (outside the DLSS-processed center) is not black/empty.

cbuffer PeripheryFillCB : register(b0)
{
uint SrcWidth;
uint SrcHeight;
uint DstWidth;
uint DstHeight;
};

Texture2D<float4> SrcTexture : register(t0);
SamplerState LinearSampler : register(s0);
RWTexture2D<float4> DstTexture : register(u0);

[numthreads(8, 8, 1)] void main(uint3 dispatchID : SV_DispatchThreadID) {
if (dispatchID.x >= DstWidth || dispatchID.y >= DstHeight)
return;

// Normalized UV with half-pixel offset for correct bilinear sampling
float2 uv = (float2(dispatchID.xy) + 0.5) / float2(DstWidth, DstHeight);
DstTexture[dispatchID.xy] = SrcTexture.SampleLevel(LinearSampler, uv, 0);
}
4 changes: 2 additions & 2 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace SharedData
bool InInterior; // If the area lacks a directional shadow light e.g. the sun or moon
bool InMapMenu; // If the world/local map is open (note that the renderer is still deferred here)
bool HideSky; // HideSky flag in WorldSpace, e.g. Blackreach
float MipBias; // Offset to mip level for TAA sharpness#
float MipBias; // Offset to mip level for TAA sharpness
float pad0;
float4 AmbientSHR;
float4 AmbientSHG;
Expand Down Expand Up @@ -52,7 +52,7 @@ namespace SharedData
bool EnableShadows;
bool ExtendShadows;
bool EnableParallaxWarpingFix;
float1 pad0;
bool pad0;
};

struct CubemapCreatorSettings
Expand Down
1 change: 1 addition & 0 deletions package/Shaders/Common/VR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ cbuffer VRValues : register(b13)
float2 EyeOffsetScale : packoffset(c0.z);
float4 EyeClipEdge[2] : packoffset(c1);
}

#endif

namespace Stereo
Expand Down
Loading
Loading