Files
NX2navi/runtime/shaders/aa_common.glsl
chrg6 bfe88e503a Add one anti-aliasing setting: the game's SMAA, off, FXAA, SMAA at its Ultra preset, or TAA.
Ocarina anti-aliases every frame with its own SMAA in three compute passes after the bloom composite. The new aa
setting (nx2navi.ini aa, the Screen tab's Anti-aliasing row) keeps that by default. off, fxaa and smaa leave out the
game's edge and weight passes and replace its composition with a pass of our own that writes the same square-rooted
RGB9E5 words into the scene target: a plain copy, an edge smoothing written here, or the SMAA reference implementation
with its area and search textures (MIT). taa is DLSS or FSR 3.1 at the scene's size, which the row sets through the
upscaler; while either runs, the game's SMAA stays whatever aa says. The game's passes are known by a hash of their
guest code. The shader build now also rebuilds a header when a file its source includes changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 15:09:16 -05:00

20 lines
1.3 KiB
GLSL

// Shared by the anti-aliasing passes (runtime/vk_aa.c) that stand in for the game's SMAA. The game's composition pass
// stores the post-processed picture into its R11G11B10F scene target as raw words: each channel is the square root of
// its linear value, the three packed together as RGB9E5 (red in bits 0-8, green 9-17, blue 18-26, the shared exponent
// in 27-31, Vulkan's E5B9G9R9 layout). The passes here write the same words through an R32_UINT view of that target.
// RGB9E5 of a non-negative colour: the shared exponent of the largest channel, each channel rounded to 9 bits of it.
uint aa_pack_rgb9e5(vec3 c) {
const float MAXV = 65408.0; // (2^9 - 1) / 2^9 * 2^15: the largest value the format holds
c = clamp(c, vec3(0.0), vec3(MAXV));
float m = max(max(c.r, c.g), c.b);
float e = max(-16.0, floor(log2(max(m, 1e-30)))) + 16.0; // biased by 15, plus one
float scale = exp2(e - 24.0); // 2^(e - 15 - 9)
if (floor(m / scale + 0.5) >= 512.0) e += 1.0, scale *= 2.0;
uvec3 q = uvec3(floor(c / scale + 0.5));
return q.r | (q.g << 9) | (q.b << 18) | (uint(e) << 27);
}
// The stored form of a linear colour: its square root, which is also the space the edges are looked for in.
vec3 aa_encode(vec3 linear) { return sqrt(max(linear, vec3(0.0))); }