feat(fatalframe2): Add game - #591
Conversation
There was a problem hiding this comment.
Pull request overview
Adds initial RenoDX game integration for Fatal Frame II, including shader overrides, shared injection constants, and a custom eye-adaptation transport path to support HDR/tone-mapping and effects controls.
Changes:
- Introduces Fatal Frame II shader set (output, bloom, grain, sharpness, final) wired into RenoDX processing.
- Adds shared injection definitions and settings-driven tone mapping/effects parameters.
- Implements perceptual eye adaptation transport (histogram + transport buffer) and hooks it into shader injection.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/games/fatalframeII/sharpness_0x84BB1EEF.ps_5_1.hlsl | Sharpness pass override with optional RCAS sharpening. |
| src/games/fatalframeII/shared.h | Game-specific injection constants/macros for tone mapping, effects, and eye adaptation. |
| src/games/fatalframeII/output/output_0x7D8A20C5.ps_5_1.hlsl | Main output shader integrating RenoDX grading and LUT shoulder extension. |
| src/games/fatalframeII/metadata.json | Registers the new game metadata entry. |
| src/games/fatalframeII/lut_extension.hlsl | Adds LUT shoulder extension + optional debug calibration tooling. |
| src/games/fatalframeII/lilium_rcas.hlsl | Adds RCAS sharpening implementation used by game shaders. |
| src/games/fatalframeII/grain_0x6DDCBB4C.ps_5_1.hlsl | Film grain pass override (vanilla/perceptual path integration). |
| src/games/fatalframeII/final/final_0x3B771412.ps_6_0.hlsl | Final pass override routed through RenoDX swapchain pass. |
| src/games/fatalframeII/eyeadaptation/transport.hlsl | Eye adaptation histogram write + resolve/transport logic + debug UI. |
| src/games/fatalframeII/eyeadaptation/adaptation.hpp | D3D12 resources + descriptor plumbing for histogram/transport buffers. |
| src/games/fatalframeII/eyeadaptation/adaptation.hlsl | Histogram encoding/decoding and temporal adaptation helpers. |
| src/games/fatalframeII/common.hlsl | Common helpers + tone mapping and LUT sampling utilities for the game. |
| src/games/fatalframeII/bloom_0xDA09ACE3.ps_5_1.hlsl | Bloom pass override with strength control + histogram write. |
| src/games/fatalframeII/addon.cpp | Addon wiring: settings UI, shader injection bindings, eye adaptation dispatch hooks. |
| src/games/fatalframeII/.skipped/film_grain_0x0AB6D76A.ps_6_5.hlsl | Stored skipped shader artifact (reference). |
| src/games/fatalframeII/.skipped/film_grain_0x0884E19F.ps_6_5.hlsl | Stored skipped shader artifact (reference). |
e1751ac to
29d8c67
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Suppressed comments (6)
src/games/fatalframeII/lilium_rcas.hlsl:118
- Noise normalization can also generate NaNs in flat regions: when
maxLuma2x == minLuma2xandnz == 0, the expression becomes0 * rcp(0). Guard the denominator with an epsilon.
float maxLuma2x = Max(Max(bLuma2x, dLuma2x, eLuma2x), fLuma2x, hLuma2x);
float minLuma2x = Min(Min(bLuma2x, dLuma2x, eLuma2x), fLuma2x, hLuma2x);
nz = saturate(abs(nz) * rcp(maxLuma2x - minLuma2x));
nz = -0.5f * nz + 1.f;
src/games/fatalframeII/lilium_rcas.hlsl:127
pixLum / eLumcan divide by zero for pure black pixels (eLum == 0), producing INF/NaN and potential speckling. ClampeLumto a small epsilon before dividing.
float rcpL = rcp(4.f * lobe + 1.f);
float pixLum = ((bLum + dLum + hLum + fLum) * lobe + eLum) * rcpL;
float3 pix = clamp((pixLum / eLum), 0.f, 4.f) * e;
src/games/fatalframeII/addon.cpp:545
- Button label uses "Github" instead of the proper "GitHub" branding/spelling.
new renodx::utils::settings::Setting{
.value_type = renodx::utils::settings::SettingValueType::BUTTON,
.label = "Github",
.section = "Links",
src/games/fatalframeII/lilium_rcas.hlsl:87
hitMinLumcan produce NaNs when the neighborhood is black (e.g.limited_max4Lum == 0leads to0 * rcp(0)). This can poison the RCAS lobe and create artifacts. Clamp the reciprocal denominator away from 0.
This issue also appears on line 114 of the same file.
float limited_max4Lum = min(max4Lum, 0.99f);
float hitMinLum = min4Lum
* rcp(4.f * limited_max4Lum);
float hitMaxLum = (peakC.x - limited_max4Lum)
* rcp(4.f * min4Lum + peakC.y);
float localLobe = max(-hitMinLum, hitMaxLum);
src/games/fatalframeII/output/output_0x7D8A20C5.ps_5_1.hlsl:309
lutOutputis computed but never applied (the lerp is commented out). This adds an extra 3D LUT sample in the composite path with no effect on output. Either re-enable the blend or remove the sample to avoid the wasted work.
float3 lutOutput = SampleSDRLUT(r0.rgb, sampleLinear_s, g_tLdrLut);
// r0.rgb = lerp(r0.rgb, lutOutput, g_vCompositeInfo.yyy);
src/games/fatalframeII/sharpness_0x84BB1EEF.ps_5_1.hlsl:35
- This shader now early-returns after the custom RCAS path, leaving the original 3Dmigoto body permanently unreachable. Keeping large blocks of dead code (plus now-unused temporaries) makes future maintenance harder and can hide accidental reintroductions. Consider deleting the unreachable block or wrapping it in
#if 0with a short note about why it’s retained.
float4 r0, r1, r2, r3;
uint4 bitmask, uiDest;
float4 fDest;
o0 = g_tTargetHPass.SampleLevel(samplePoint_s, v1.xy, 0);
// We skip this shader
if (CUSTOM_SHARPNESS > 0.f) {
o0.rgb = ApplyRCAS(o0.rgb, v1.xy, g_tTargetHPass, samplePoint_s);
}
return;
r0.x = cmp(0 < g_cbColorInfo.w);
r0.yz = -g_cbScreenScale.zw + v1.xy;
r0.yzw = g_tTargetHPass.SampleLevel(samplePoint_s, r0.yz, 0).xyz;
| #endif | ||
| #define CUSTOM_EYE_ADAPTATION CUSTOM_FLAGS | ||
| #define CUSTOM_EYE_ADAPTATION_AS_UINT CUSTOM_FLAGS_AS_UINT | ||
| #define CUSTOM_EYE_ADAPTATION_PERCEPTUAL ((RENODX_TONE_MAP_TYPE != RENODX_TONE_MAP_TYPE_VANILLA) && ((CUSTOM_EYE_ADAPTATION_AS_UINT & CUSTOM_EYE_ADAPTATION_FLAGS__PERCEPTUAL) != 0u)) |
No description provided.