From dd9994482c3046a237c26dc215eb1f9b9d7e91ee Mon Sep 17 00:00:00 2001 From: Jonatas Esteves Date: Wed, 8 Sep 2021 14:48:23 -0300 Subject: [PATCH 1/2] SMAA: Expose more quality settings - Expose all the configuration settings used by the quality presets to allow fine-tuning of edge detection. - Changed default edge detection technique from luma to color since in my tests that always yields better results. - Increased quality to ultra in default preset. - Deleted the duplication of the fragment shader part of the lib, as I figured out how to include the lib twice with different defines for the vertex and fragment passes. That is necessary probably because discard cannot be used in vertex shaders in RetroArch, indicated in a comment in the lib as a possible restriction in some compilers. - Include license headers to make clear that all my contributions are released on the public domain under the terms of the Unlicense. Anyone can do whatever they want with this. --- README.md | 2 +- anti-aliasing/shaders/smaa/SMAA.frag | 710 -------------------- anti-aliasing/shaders/smaa/smaa-pass0.slang | 28 +- anti-aliasing/shaders/smaa/smaa-pass1.slang | 27 +- anti-aliasing/shaders/smaa/smaa-pass2.slang | 9 +- anti-aliasing/smaa+sharpen.slangp | 9 +- anti-aliasing/smaa.slangp | 9 +- 7 files changed, 69 insertions(+), 725 deletions(-) delete mode 100644 anti-aliasing/shaders/smaa/SMAA.frag diff --git a/README.md b/README.md index 146e4de..605bbfc 100644 --- a/README.md +++ b/README.md @@ -614,7 +614,7 @@ layout(push_constant) uniform Push ### Samplers Which samplers are used for textures are specified by the preset format. -The sampler remains constant throughout the frame, there is currently no way to select samplers on a frame-by-frame basic. +The sampler remains constant throughout the frame, there is currently no way to select samplers on a frame-by-frame basis. This is mostly to make it possible to use the spec in GLES2 as GLES2 has no concept of separate samplers and images. ### sRGB diff --git a/anti-aliasing/shaders/smaa/SMAA.frag b/anti-aliasing/shaders/smaa/SMAA.frag deleted file mode 100644 index d4f1b1a..0000000 --- a/anti-aliasing/shaders/smaa/SMAA.frag +++ /dev/null @@ -1,710 +0,0 @@ -/** - * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) - * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) - * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) - * Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com) - * Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to - * do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. As clarification, there - * is no requirement that the copyright notice and permission be included in - * binary distributions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - -//----------------------------------------------------------------------------- -// Edge Detection Pixel Shaders (First Pass) - -/** - * Luma Edge Detection - * - * IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and - * thus 'colorTex' should be a non-sRGB texture. - */ -float2 SMAALumaEdgeDetectionPS(float2 texcoord, - float4 offset[3], - SMAATexture2D(colorTex) - #if SMAA_PREDICATION - , SMAATexture2D(predicationTex) - #endif - ) { - // Calculate the threshold: - #if SMAA_PREDICATION - float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, SMAATexturePass2D(predicationTex)); - #else - float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); - #endif - - // Calculate lumas: - float3 weights = float3(0.2126, 0.7152, 0.0722); - float L = dot(SMAASamplePoint(colorTex, texcoord).rgb, weights); - - float Lleft = dot(SMAASamplePoint(colorTex, offset[0].xy).rgb, weights); - float Ltop = dot(SMAASamplePoint(colorTex, offset[0].zw).rgb, weights); - - // We do the usual threshold: - float4 delta; - delta.xy = abs(L - float2(Lleft, Ltop)); - float2 edges = step(threshold, delta.xy); - - // Then discard if there is no edge: - if (dot(edges, float2(1.0, 1.0)) == 0.0) - discard; - - // Calculate right and bottom deltas: - float Lright = dot(SMAASamplePoint(colorTex, offset[1].xy).rgb, weights); - float Lbottom = dot(SMAASamplePoint(colorTex, offset[1].zw).rgb, weights); - delta.zw = abs(L - float2(Lright, Lbottom)); - - // Calculate the maximum delta in the direct neighborhood: - float2 maxDelta = max(delta.xy, delta.zw); - - // Calculate left-left and top-top deltas: - float Lleftleft = dot(SMAASamplePoint(colorTex, offset[2].xy).rgb, weights); - float Ltoptop = dot(SMAASamplePoint(colorTex, offset[2].zw).rgb, weights); - delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop)); - - // Calculate the final maximum delta: - maxDelta = max(maxDelta.xy, delta.zw); - float finalDelta = max(maxDelta.x, maxDelta.y); - - // Local contrast adaptation: - edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); - - return edges; -} - -/** - * Color Edge Detection - * - * IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and - * thus 'colorTex' should be a non-sRGB texture. - */ -float2 SMAAColorEdgeDetectionPS(float2 texcoord, - float4 offset[3], - SMAATexture2D(colorTex) - #if SMAA_PREDICATION - , SMAATexture2D(predicationTex) - #endif - ) { - // Calculate the threshold: - #if SMAA_PREDICATION - float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex); - #else - float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); - #endif - - // Calculate color deltas: - float4 delta; - float3 C = SMAASamplePoint(colorTex, texcoord).rgb; - - float3 Cleft = SMAASamplePoint(colorTex, offset[0].xy).rgb; - float3 t = abs(C - Cleft); - delta.x = max(max(t.r, t.g), t.b); - - float3 Ctop = SMAASamplePoint(colorTex, offset[0].zw).rgb; - t = abs(C - Ctop); - delta.y = max(max(t.r, t.g), t.b); - - // We do the usual threshold: - float2 edges = step(threshold, delta.xy); - - // Then discard if there is no edge: - if (dot(edges, float2(1.0, 1.0)) == 0.0) - discard; - - // Calculate right and bottom deltas: - float3 Cright = SMAASamplePoint(colorTex, offset[1].xy).rgb; - t = abs(C - Cright); - delta.z = max(max(t.r, t.g), t.b); - - float3 Cbottom = SMAASamplePoint(colorTex, offset[1].zw).rgb; - t = abs(C - Cbottom); - delta.w = max(max(t.r, t.g), t.b); - - // Calculate the maximum delta in the direct neighborhood: - float2 maxDelta = max(delta.xy, delta.zw); - - // Calculate left-left and top-top deltas: - float3 Cleftleft = SMAASamplePoint(colorTex, offset[2].xy).rgb; - t = abs(C - Cleftleft); - delta.z = max(max(t.r, t.g), t.b); - - float3 Ctoptop = SMAASamplePoint(colorTex, offset[2].zw).rgb; - t = abs(C - Ctoptop); - delta.w = max(max(t.r, t.g), t.b); - - // Calculate the final maximum delta: - maxDelta = max(maxDelta.xy, delta.zw); - float finalDelta = max(maxDelta.x, maxDelta.y); - - // Local contrast adaptation: - edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); - - return edges; -} - -/** - * Depth Edge Detection - */ -float2 SMAADepthEdgeDetectionPS(float2 texcoord, - float4 offset[3], - SMAATexture2D(depthTex)) { - float3 neighbours = SMAAGatherNeighbours(texcoord, offset, SMAATexturePass2D(depthTex)); - float2 delta = abs(neighbours.xx - float2(neighbours.y, neighbours.z)); - float2 edges = step(SMAA_DEPTH_THRESHOLD, delta); - - if (dot(edges, float2(1.0, 1.0)) == 0.0) - discard; - - return edges; -} - -//----------------------------------------------------------------------------- -// Diagonal Search Functions - -#if !defined(SMAA_DISABLE_DIAG_DETECTION) - -/** - * Allows to decode two binary values from a bilinear-filtered access. - */ -float2 SMAADecodeDiagBilinearAccess(float2 e) { - // Bilinear access for fetching 'e' have a 0.25 offset, and we are - // interested in the R and G edges: - // - // +---G---+-------+ - // | x o R x | - // +-------+-------+ - // - // Then, if one of these edge is enabled: - // Red: (0.75 * X + 0.25 * 1) => 0.25 or 1.0 - // Green: (0.75 * 1 + 0.25 * X) => 0.75 or 1.0 - // - // This function will unpack the values (mad + mul + round): - // wolframalpha.com: round(x * abs(5 * x - 5 * 0.75)) plot 0 to 1 - e.r = e.r * abs(5.0 * e.r - 5.0 * 0.75); - return round(e); -} - -float4 SMAADecodeDiagBilinearAccess(float4 e) { - e.rb = e.rb * abs(5.0 * e.rb - 5.0 * 0.75); - return round(e); -} - -/** - * These functions allows to perform diagonal pattern searches. - */ -float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { - float4 coord = float4(texcoord, -1.0, 1.0); - float3 t = float3(SMAA_RT_METRICS.xy, 1.0); - while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && - coord.w > 0.9) { - coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); - e = SMAASampleLevelZero(edgesTex, coord.xy).rg; - coord.w = dot(e, float2(0.5, 0.5)); - } - return coord.zw; -} - -float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { - float4 coord = float4(texcoord, -1.0, 1.0); - coord.x += 0.25 * SMAA_RT_METRICS.x; // See @SearchDiag2Optimization - float3 t = float3(SMAA_RT_METRICS.xy, 1.0); - while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && - coord.w > 0.9) { - coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); - - // @SearchDiag2Optimization - // Fetch both edges at once using bilinear filtering: - e = SMAASampleLevelZero(edgesTex, coord.xy).rg; - e = SMAADecodeDiagBilinearAccess(e); - - // Non-optimized version: - // e.g = SMAASampleLevelZero(edgesTex, coord.xy).g; - // e.r = SMAASampleLevelZeroOffset(edgesTex, coord.xy, int2(1, 0)).r; - - coord.w = dot(e, float2(0.5, 0.5)); - } - return coord.zw; -} - -/** - * Similar to SMAAArea, this calculates the area corresponding to a certain - * diagonal distance and crossing edges 'e'. - */ -float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset) { - float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE_DIAG, SMAA_AREATEX_MAX_DISTANCE_DIAG), e, dist); - - // We do a scale and bias for mapping to texel space: - texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); - - // Diagonal areas are on the second half of the texture: - texcoord.x += 0.5; - - // Move to proper place, according to the subpixel offset: - texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset; - - // Do it! - return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); -} - -/** - * This searches for diagonal patterns and returns the corresponding weights. - */ -float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex), SMAATexture2D(areaTex), float2 texcoord, float2 e, float4 subsampleIndices) { - float2 weights = float2(0.0, 0.0); - - // Search for the line ends: - float4 d; - float2 end; - if (e.r > 0.0) { - d.xz = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, 1.0), end); - d.x += float(end.y > 0.9); - } else - d.xz = float2(0.0, 0.0); - d.yw = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, -1.0), end); - - SMAA_BRANCH - if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 - // Fetch the crossing edges: - float4 coords = mad(float4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), SMAA_RT_METRICS.xyxy, texcoord.xyxy); - float4 c; - c.xy = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).rg; - c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).rg; - c.yxwz = SMAADecodeDiagBilinearAccess(c.xyzw); - - // Non-optimized version: - // float4 coords = mad(float4(-d.x, d.x, d.y, -d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); - // float4 c; - // c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; - // c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0)).r; - // c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).g; - // c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1)).r; - - // Merge crossing edges at each side into a single value: - float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); - - // Remove the crossing edge if we didn't found the end of the line: - SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); - - // Fetch the areas for this line: - weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.z); - } - - // Search for the line ends: - d.xz = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, -1.0), end); - if (SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r > 0.0) { - d.yw = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, 1.0), end); - d.y += float(end.y > 0.9); - } else - d.yw = float2(0.0, 0.0); - - SMAA_BRANCH - if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 - // Fetch the crossing edges: - float4 coords = mad(float4(-d.x, -d.x, d.y, d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); - float4 c; - c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; - c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, -1)).r; - c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).gr; - float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); - - // Remove the crossing edge if we didn't found the end of the line: - SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); - - // Fetch the areas for this line: - weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.w).gr; - } - - return weights; -} -#endif - -//----------------------------------------------------------------------------- -// Horizontal/Vertical Search Functions - -/** - * This allows to determine how much length should we add in the last step - * of the searches. It takes the bilinearly interpolated edge (see - * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and - * crossing edges are active. - */ -float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset) { - // The texture is flipped vertically, with left and right cases taking half - // of the space horizontally: - float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5, -1.0); - float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0); - - // Scale and bias to access texel centers: - scale += float2(-1.0, 1.0); - bias += float2( 0.5, -0.5); - - // Convert from pixel coordinates to texcoords: - // (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped) - scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; - bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; - - // Lookup the search texture: - return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, mad(scale, e, bias))); -} - -/** - * Horizontal/vertical search functions for the 2nd pass. - */ -float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { - /** - * @PSEUDO_GATHER4 - * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to - * sample between edge, thus fetching four edges in a row. - * Sampling with different offsets in each direction allows to disambiguate - * which edges are active from the four fetched ones. - */ - float2 e = float2(0.0, 1.0); - while (texcoord.x > end && - e.g > 0.8281 && // Is there some edge not activated? - e.r == 0.0) { // Or is there a crossing edge that breaks the line? - e = SMAASampleLevelZero(edgesTex, texcoord).rg; - texcoord = mad(-float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); - } - - float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0), 3.25); - return mad(SMAA_RT_METRICS.x, offset, texcoord.x); - - // Non-optimized version: - // We correct the previous (-0.25, -0.125) offset we applied: - // texcoord.x += 0.25 * SMAA_RT_METRICS.x; - - // The searches are bias by 1, so adjust the coords accordingly: - // texcoord.x += SMAA_RT_METRICS.x; - - // Disambiguate the length added by the last step: - // texcoord.x += 2.0 * SMAA_RT_METRICS.x; // Undo last step - // texcoord.x -= SMAA_RT_METRICS.x * (255.0 / 127.0) * SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0); - // return mad(SMAA_RT_METRICS.x, offset, texcoord.x); -} - -float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { - float2 e = float2(0.0, 1.0); - while (texcoord.x < end && - e.g > 0.8281 && // Is there some edge not activated? - e.r == 0.0) { // Or is there a crossing edge that breaks the line? - e = SMAASampleLevelZero(edgesTex, texcoord).rg; - texcoord = mad(float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); - } - float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.5), 3.25); - return mad(-SMAA_RT_METRICS.x, offset, texcoord.x); -} - -float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { - float2 e = float2(1.0, 0.0); - while (texcoord.y > end && - e.r > 0.8281 && // Is there some edge not activated? - e.g == 0.0) { // Or is there a crossing edge that breaks the line? - e = SMAASampleLevelZero(edgesTex, texcoord).rg; - texcoord = mad(-float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); - } - float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.0), 3.25); - return mad(SMAA_RT_METRICS.y, offset, texcoord.y); -} - -float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { - float2 e = float2(1.0, 0.0); - while (texcoord.y < end && - e.r > 0.8281 && // Is there some edge not activated? - e.g == 0.0) { // Or is there a crossing edge that breaks the line? - e = SMAASampleLevelZero(edgesTex, texcoord).rg; - texcoord = mad(float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); - } - float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.5), 3.25); - return mad(-SMAA_RT_METRICS.y, offset, texcoord.y); -} - -/** - * Ok, we have the distance and both crossing edges. So, what are the areas - * at each side of current edge? - */ -float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset) { - // Rounding prevents precision errors of bilinear filtering: - float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * float2(e1, e2)), dist); - - // We do a scale and bias for mapping to texel space: - texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); - - // Move to proper place, according to the subpixel offset: - texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y); - - // Do it! - return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); -} - -//----------------------------------------------------------------------------- -// Corner Detection Functions - -void SMAADetectHorizontalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { - #if !defined(SMAA_DISABLE_CORNER_DETECTION) - float2 leftRight = step(d.xy, d.yx); - float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; - - rounding /= leftRight.x + leftRight.y; // Reduce blending for pixels in the center of a line. - - float2 factor = float2(1.0, 1.0); - factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, 1)).r; - factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, 1)).r; - factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, -2)).r; - factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, -2)).r; - - weights *= saturate(factor); - #endif -} - -void SMAADetectVerticalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { - #if !defined(SMAA_DISABLE_CORNER_DETECTION) - float2 leftRight = step(d.xy, d.yx); - float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; - - rounding /= leftRight.x + leftRight.y; - - float2 factor = float2(1.0, 1.0); - factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2( 1, 0)).g; - factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2( 1, 1)).g; - factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(-2, 0)).g; - factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(-2, 1)).g; - - weights *= saturate(factor); - #endif -} - -//----------------------------------------------------------------------------- -// Blending Weight Calculation Pixel Shader (Second Pass) - -float4 SMAABlendingWeightCalculationPS(float2 texcoord, - float2 pixcoord, - float4 offset[3], - SMAATexture2D(edgesTex), - SMAATexture2D(areaTex), - SMAATexture2D(searchTex), - float4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES. - float4 weights = float4(0.0, 0.0, 0.0, 0.0); - - float2 e = SMAASample(edgesTex, texcoord).rg; - - SMAA_BRANCH - if (e.g > 0.0) { // Edge at north - #if !defined(SMAA_DISABLE_DIAG_DETECTION) - // Diagonals have both north and west edges, so searching for them in - // one of the boundaries is enough. - weights.rg = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex), SMAATexturePass2D(areaTex), texcoord, e, subsampleIndices); - - // We give priority to diagonals, so if we find a diagonal we skip - // horizontal/vertical processing. - SMAA_BRANCH - if (weights.r == -weights.g) { // weights.r + weights.g == 0.0 - #endif - - float2 d; - - // Find the distance to the left: - float3 coords; - coords.x = SMAASearchXLeft(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].xy, offset[2].x); - coords.y = offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET) - d.x = coords.x; - - // Now fetch the left crossing edges, two at a time using bilinear - // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to - // discern what value each edge has: - float e1 = SMAASampleLevelZero(edgesTex, coords.xy).r; - - // Find the distance to the right: - coords.z = SMAASearchXRight(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].zw, offset[2].y); - d.y = coords.z; - - // We want the distances to be in pixel units (doing this here allow to - // better interleave arithmetic and memory accesses): - d = abs(round(mad(SMAA_RT_METRICS.zz, d, -pixcoord.xx))); - - // SMAAArea below needs a sqrt, as the areas texture is compressed - // quadratically: - float2 sqrt_d = sqrt(d); - - // Fetch the right crossing edges: - float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.zy, int2(1, 0)).r; - - // Ok, we know how this pattern looks like, now it is time for getting - // the actual area: - weights.rg = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.y); - - // Fix corners: - coords.y = texcoord.y; - SMAADetectHorizontalCornerPattern(SMAATexturePass2D(edgesTex), weights.rg, coords.xyzy, d); - - #if !defined(SMAA_DISABLE_DIAG_DETECTION) - } else - e.r = 0.0; // Skip vertical processing. - #endif - } - - SMAA_BRANCH - if (e.r > 0.0) { // Edge at west - float2 d; - - // Find the distance to the top: - float3 coords; - coords.y = SMAASearchYUp(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].xy, offset[2].z); - coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x; - d.x = coords.y; - - // Fetch the top crossing edges: - float e1 = SMAASampleLevelZero(edgesTex, coords.xy).g; - - // Find the distance to the bottom: - coords.z = SMAASearchYDown(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].zw, offset[2].w); - d.y = coords.z; - - // We want the distances to be in pixel units: - d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixcoord.yy))); - - // SMAAArea below needs a sqrt, as the areas texture is compressed - // quadratically: - float2 sqrt_d = sqrt(d); - - // Fetch the bottom crossing edges: - float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.xz, int2(0, 1)).g; - - // Get the area for this direction: - weights.ba = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.x); - - // Fix corners: - coords.x = texcoord.x; - SMAADetectVerticalCornerPattern(SMAATexturePass2D(edgesTex), weights.ba, coords.xyxz, d); - } - - return weights; -} - -//----------------------------------------------------------------------------- -// Neighborhood Blending Pixel Shader (Third Pass) - -float4 SMAANeighborhoodBlendingPS(float2 texcoord, - float4 offset, - SMAATexture2D(colorTex), - SMAATexture2D(blendTex) - #if SMAA_REPROJECTION - , SMAATexture2D(velocityTex) - #endif - ) { - // Fetch the blending weights for current pixel: - float4 a; - a.x = SMAASample(blendTex, offset.xy).a; // Right - a.y = SMAASample(blendTex, offset.zw).g; // Top - a.wz = SMAASample(blendTex, texcoord).xz; // Bottom / Left - - // Is there any blending weight with a value greater than 0.0? - SMAA_BRANCH - if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5) { - float4 color = SMAASampleLevelZero(colorTex, texcoord); - - #if SMAA_REPROJECTION - float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord)); - - // Pack velocity into the alpha channel: - color.a = sqrt(5.0 * length(velocity)); - #endif - - return color; - } else { - bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical) - - // Calculate the blending offsets: - float4 blendingOffset = float4(0.0, a.y, 0.0, a.w); - float2 blendingWeight = a.yw; - SMAAMovc(bool4(h, h, h, h), blendingOffset, float4(a.x, 0.0, a.z, 0.0)); - SMAAMovc(bool2(h, h), blendingWeight, a.xz); - blendingWeight /= dot(blendingWeight, float2(1.0, 1.0)); - - // Calculate the texture coordinates: - float4 blendingCoord = mad(blendingOffset, float4(SMAA_RT_METRICS.xy, -SMAA_RT_METRICS.xy), texcoord.xyxy); - - // We exploit bilinear filtering to mix current pixel with the chosen - // neighbor: - float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy); - color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw); - - #if SMAA_REPROJECTION - // Antialias velocity for proper reprojection in a later stage: - float2 velocity = blendingWeight.x * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.xy)); - velocity += blendingWeight.y * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.zw)); - - // Pack velocity into the alpha channel: - color.a = sqrt(5.0 * length(velocity)); - #endif - - return color; - } -} - -//----------------------------------------------------------------------------- -// Temporal Resolve Pixel Shader (Optional Pass) - -float4 SMAAResolvePS(float2 texcoord, - SMAATexture2D(currentColorTex), - SMAATexture2D(previousColorTex) - #if SMAA_REPROJECTION - , SMAATexture2D(velocityTex) - #endif - ) { - #if SMAA_REPROJECTION - // Velocity is assumed to be calculated for motion blur, so we need to - // inverse it for reprojection: - float2 velocity = -SMAA_DECODE_VELOCITY(SMAASamplePoint(velocityTex, texcoord).rg); - - // Fetch current pixel: - float4 current = SMAASamplePoint(currentColorTex, texcoord); - - // Reproject current coordinates and fetch previous pixel: - float4 previous = SMAASamplePoint(previousColorTex, texcoord + velocity); - - // Attenuate the previous pixel if the velocity is different: - float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0; - float weight = 0.5 * saturate(1.0 - sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE); - - // Blend the pixels according to the calculated weight: - return lerp(current, previous, weight); - #else - // Just blend the pixels: - float4 current = SMAASamplePoint(currentColorTex, texcoord); - float4 previous = SMAASamplePoint(previousColorTex, texcoord); - return lerp(current, previous, 0.5); - #endif -} - -//----------------------------------------------------------------------------- -// Separate Multisamples Pixel Shader (Optional Pass) - -#ifdef SMAALoad -void SMAASeparatePS(float4 position, - float2 texcoord, - out float4 target0, - out float4 target1, - SMAATexture2DMS2(colorTexMS)) { - int2 pos = int2(position.xy); - target0 = SMAALoad(colorTexMS, pos, 0); - target1 = SMAALoad(colorTexMS, pos, 1); -} -#endif - -//----------------------------------------------------------------------------- diff --git a/anti-aliasing/shaders/smaa/smaa-pass0.slang b/anti-aliasing/shaders/smaa/smaa-pass0.slang index 4efdc5a..0fbab2a 100644 --- a/anti-aliasing/shaders/smaa/smaa-pass0.slang +++ b/anti-aliasing/shaders/smaa/smaa-pass0.slang @@ -1,9 +1,14 @@ #version 450 +// SPDX-License-Identifier: Unlicense #pragma name SMAA_Pass0 //----------------------------------------------------------------------------- // Edge Detection Shaders (First Pass) -#pragma parameter SMAA_EDT "SMAA Edge Detection: Luma | Color" 0.0 0.0 1.0 1.0 +#pragma parameter SMAA_EDT "SMAA Edge Detection: Luma | Color" 1.0 0.0 1.0 1.0 +#pragma parameter SMAA_THRESHOLD "SMAA Threshold" 0.05 0.01 0.5 0.01 +#pragma parameter SMAA_MAX_SEARCH_STEPS "SMAA Max Search Steps" 32.0 4.0 112.0 1.0 +#pragma parameter SMAA_MAX_SEARCH_STEPS_DIAG "SMAA Max Search Steps Diagonal" 16.0 4.0 20.0 1.0 +#pragma parameter SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR "SMAA Local Contrast Adapt. Factor" 2.0 1.0 4.0 0.1 layout(push_constant) uniform Push { vec4 SourceSize; @@ -11,6 +16,10 @@ layout(push_constant) uniform Push { vec4 OutputSize; uint FrameCount; float SMAA_EDT; + float SMAA_THRESHOLD; + float SMAA_MAX_SEARCH_STEPS; + float SMAA_MAX_SEARCH_STEPS_DIAG; + float SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR; } params; layout(std140, set = 0, binding = 0) uniform UBO { @@ -19,8 +28,15 @@ layout(std140, set = 0, binding = 0) uniform UBO { #define SMAA_RT_METRICS vec4(params.SourceSize.z, params.SourceSize.w, params.SourceSize.x, params.SourceSize.y) #define SMAA_GLSL_4 -#define SMAA_INCLUDE_PS 0 -#include "SMAA.hlsl" + +float THRESHOLD = params.SMAA_THRESHOLD; +float MAX_SEARCH_STEPS = params.SMAA_MAX_SEARCH_STEPS; +float MAX_SEARCH_STEPS_DIAG = params.SMAA_MAX_SEARCH_STEPS_DIAG; +float LOCAL_CONTRAST_ADAPTATION_FACTOR = params.SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR; +#define SMAA_THRESHOLD THRESHOLD +#define SMAA_MAX_SEARCH_STEPS MAX_SEARCH_STEPS +#define SMAA_MAX_SEARCH_STEPS_DIAG MAX_SEARCH_STEPS_DIAG +#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR LOCAL_CONTRAST_ADAPTATION_FACTOR #pragma stage vertex layout(location = 0) in vec4 Position; @@ -28,6 +44,9 @@ layout(location = 1) in vec2 TexCoord; layout(location = 0) out vec2 vTexCoord; layout(location = 1) out vec4 offset[3]; +#define SMAA_INCLUDE_PS 0 +#include "SMAA.hlsl" + void main() { gl_Position = global.MVP * Position; vTexCoord = TexCoord; @@ -40,7 +59,8 @@ layout(location = 1) in vec4 offset[3]; layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform sampler2D Source; -#include "SMAA.frag" +#define SMAA_INCLUDE_VS 0 +#include "SMAA.hlsl" void main() { if (params.SMAA_EDT == 0.0) { diff --git a/anti-aliasing/shaders/smaa/smaa-pass1.slang b/anti-aliasing/shaders/smaa/smaa-pass1.slang index 3508492..8322279 100644 --- a/anti-aliasing/shaders/smaa/smaa-pass1.slang +++ b/anti-aliasing/shaders/smaa/smaa-pass1.slang @@ -1,13 +1,23 @@ #version 450 +// SPDX-License-Identifier: Unlicense #pragma name SMAA_Pass1 //----------------------------------------------------------------------------- // Blending Weight Calculation Shader (Second Pass) +#pragma parameter SMAA_THRESHOLD "SMAA Threshold" 0.05 0.01 0.5 0.01 +#pragma parameter SMAA_MAX_SEARCH_STEPS "SMAA Max Search Steps" 32.0 4.0 112.0 1.0 +#pragma parameter SMAA_MAX_SEARCH_STEPS_DIAG "SMAA Max Search Steps Diagonal" 16.0 4.0 20.0 1.0 +#pragma parameter SMAA_CORNER_ROUNDING "SMAA Corner Rounding" 25.0 0.0 100.0 1.0 + layout(push_constant) uniform Push { vec4 SourceSize; vec4 OriginalSize; vec4 OutputSize; uint FrameCount; + float SMAA_THRESHOLD; + float SMAA_MAX_SEARCH_STEPS; + float SMAA_MAX_SEARCH_STEPS_DIAG; + float SMAA_CORNER_ROUNDING; } params; layout(std140, set = 0, binding = 0) uniform UBO { @@ -16,8 +26,15 @@ layout(std140, set = 0, binding = 0) uniform UBO { #define SMAA_RT_METRICS vec4(params.SourceSize.z, params.SourceSize.w, params.SourceSize.x, params.SourceSize.y) #define SMAA_GLSL_4 -#define SMAA_INCLUDE_PS 0 -#include "SMAA.hlsl" + +float THRESHOLD = params.SMAA_THRESHOLD; +float MAX_SEARCH_STEPS = params.SMAA_MAX_SEARCH_STEPS; +float MAX_SEARCH_STEPS_DIAG = params.SMAA_MAX_SEARCH_STEPS_DIAG; +float CORNER_ROUNDING = params.SMAA_CORNER_ROUNDING; +#define SMAA_THRESHOLD THRESHOLD +#define SMAA_MAX_SEARCH_STEPS MAX_SEARCH_STEPS +#define SMAA_MAX_SEARCH_STEPS_DIAG MAX_SEARCH_STEPS_DIAG +#define SMAA_CORNER_ROUNDING CORNER_ROUNDING #pragma stage vertex layout(location = 0) in vec4 Position; @@ -26,6 +43,9 @@ layout(location = 0) out vec2 vTexCoord; layout(location = 1) out vec2 pixcoord; layout(location = 2) out vec4 offset[3]; +#define SMAA_INCLUDE_PS 0 +#include "SMAA.hlsl" + void main() { gl_Position = global.MVP * Position; vTexCoord = TexCoord; @@ -41,7 +61,8 @@ layout(set = 0, binding = 2) uniform sampler2D Source; layout(set = 0, binding = 3) uniform sampler2D areaTex; layout(set = 0, binding = 4) uniform sampler2D searchTex; -#include "SMAA.frag" +#define SMAA_INCLUDE_VS 0 +#include "SMAA.hlsl" void main() { vec4 subsampleIndices = vec4(0.0); diff --git a/anti-aliasing/shaders/smaa/smaa-pass2.slang b/anti-aliasing/shaders/smaa/smaa-pass2.slang index 556b062..8ecd0ec 100644 --- a/anti-aliasing/shaders/smaa/smaa-pass2.slang +++ b/anti-aliasing/shaders/smaa/smaa-pass2.slang @@ -1,4 +1,5 @@ #version 450 +// SPDX-License-Identifier: Unlicense #pragma name SMAA_Pass2 //----------------------------------------------------------------------------- // Neighborhood Blending Shader (Third Pass) @@ -16,8 +17,6 @@ layout(std140, set = 0, binding = 0) uniform UBO { #define SMAA_RT_METRICS vec4(params.SourceSize.z, params.SourceSize.w, params.SourceSize.x, params.SourceSize.y) #define SMAA_GLSL_4 -#define SMAA_INCLUDE_PS 0 -#include "SMAA.hlsl" #pragma stage vertex layout(location = 0) in vec4 Position; @@ -25,6 +24,9 @@ layout(location = 1) in vec2 TexCoord; layout(location = 0) out vec2 vTexCoord; layout(location = 1) out vec4 offset; +#define SMAA_INCLUDE_PS 0 +#include "SMAA.hlsl" + void main() { gl_Position = global.MVP * Position; vTexCoord = TexCoord; @@ -38,7 +40,8 @@ layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform sampler2D Source; layout(set = 0, binding = 3) uniform sampler2D SMAA_Input; -#include "SMAA.frag" +#define SMAA_INCLUDE_VS 0 +#include "SMAA.hlsl" void main() { FragColor = SMAANeighborhoodBlendingPS(vTexCoord, offset, SMAA_Input, Source); diff --git a/anti-aliasing/smaa+sharpen.slangp b/anti-aliasing/smaa+sharpen.slangp index 31d82f4..18297c6 100644 --- a/anti-aliasing/smaa+sharpen.slangp +++ b/anti-aliasing/smaa+sharpen.slangp @@ -30,8 +30,13 @@ filter_linear4 = false scale_type4 = source scale4 = 1.0 -parameters = "SMAA_EDT;SHARPEN;CONTR;DETAILS" +parameters = "SMAA_EDT;SMAA_THRESHOLD;SMAA_MAX_SEARCH_STEPS;SMAA_MAX_SEARCH_STEPS_DIAG;SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR;SMAA_CORNER_ROUNDING;SHARPEN;CONTR;DETAILS" SMAA_EDT = 1.0 +SMAA_THRESHOLD = 0.05 +SMAA_MAX_SEARCH_STEPS = 40 +SMAA_MAX_SEARCH_STEPS_DIAG = 20 +SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR = 2.5 +SMAA_CORNER_ROUNDING = 50.0 SHARPEN = 0.9 -CONTR = 0.01 +CONTR = 0.0 DETAILS = 0.2 diff --git a/anti-aliasing/smaa.slangp b/anti-aliasing/smaa.slangp index 5163548..f8c5479 100644 --- a/anti-aliasing/smaa.slangp +++ b/anti-aliasing/smaa.slangp @@ -25,5 +25,10 @@ textures = "areaTex;searchTex" areaTex = shaders/smaa/AreaTex.png searchTex = shaders/smaa/SearchTex.png -parameters = "SMAA_EDT" -SMAA_EDT = 0.0 +parameters = "SMAA_EDT;SMAA_THRESHOLD;SMAA_MAX_SEARCH_STEPS;SMAA_MAX_SEARCH_STEPS_DIAG;SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR;SMAA_CORNER_ROUNDING" +SMAA_EDT = 1.0 +SMAA_THRESHOLD = 0.05 +SMAA_MAX_SEARCH_STEPS = 32 +SMAA_MAX_SEARCH_STEPS_DIAG = 16 +SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR = 2.0 +SMAA_CORNER_ROUNDING = 25.0 From b0b12b6a642ccb0a3e746172641c3bddf91d7723 Mon Sep 17 00:00:00 2001 From: Jonatas Esteves Date: Wed, 8 Sep 2021 18:16:54 -0300 Subject: [PATCH 2/2] FSR: Improve quality of Film Grain and Anti-Aliasing - New implementation of Film Grain that doesn't suck, so we can turn it up a nod by default. Supports RGB noise and shaping the distribution curve to control noise modulation. The previous implementation was just a placeholder, it was very basic. - Greatly increased Anti-Aliasing quality in default preset. - Include license headers to make clear that all my contributions are released on the public domain under the terms of the Unlicense. Anyone can do whatever they want with this. --- fsr/fsr.slangp | 6 +++-- fsr/shaders/fsr-pass0.slang | 13 ++++------- fsr/shaders/fsr-pass1.slang | 45 +++++++++++++++++++++++++++++++------ fsr/smaa+fsr.slangp | 11 +++++++-- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/fsr/fsr.slangp b/fsr/fsr.slangp index d72a9a8..dcbce21 100644 --- a/fsr/fsr.slangp +++ b/fsr/fsr.slangp @@ -10,6 +10,8 @@ filter_linear1 = true scale_type1 = source scale1 = 1.0 -parameters = "FSR_SHARPENING;FSR_FILMGRAIN" +parameters = "FSR_SHARPENING;FSR_FILMGRAIN;FSR_GRAINCOLOR;FSR_GRAINPDF" FSR_SHARPENING = 0.3 -FSR_FILMGRAIN = 0.10 +FSR_FILMGRAIN = 0.3 +FSR_GRAINCOLOR = 1.0 +FSR_GRAINPDF = 0.3 diff --git a/fsr/shaders/fsr-pass0.slang b/fsr/shaders/fsr-pass0.slang index 6abf481..b0028ba 100644 --- a/fsr/shaders/fsr-pass0.slang +++ b/fsr/shaders/fsr-pass0.slang @@ -1,4 +1,5 @@ #version 450 +// SPDX-License-Identifier: Unlicense #pragma name FSR_EASU // FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING @@ -40,15 +41,9 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define FSR_EASU_F 1 AU4 con0, con1, con2, con3; -AF4 FsrEasuRF(AF2 p) { - return textureGather(Source, p, 0); -} -AF4 FsrEasuGF(AF2 p) { - return textureGather(Source, p, 1); -} -AF4 FsrEasuBF(AF2 p) { - return textureGather(Source, p, 2); -} +AF4 FsrEasuRF(AF2 p) { return textureGather(Source, p, 0); } +AF4 FsrEasuGF(AF2 p) { return textureGather(Source, p, 1); } +AF4 FsrEasuBF(AF2 p) { return textureGather(Source, p, 2); } #include "ffx_fsr1.h" diff --git a/fsr/shaders/fsr-pass1.slang b/fsr/shaders/fsr-pass1.slang index 5574444..d9537ab 100644 --- a/fsr/shaders/fsr-pass1.slang +++ b/fsr/shaders/fsr-pass1.slang @@ -1,4 +1,5 @@ #version 450 +// SPDX-License-Identifier: Unlicense #pragma name FSR_RCAS // FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING @@ -8,7 +9,9 @@ // scale1 = 1.0 #pragma parameter FSR_SHARPENING "FSR RCAS Sharpening Amount (Lower = Sharper)" 0.2 0.0 2.0 0.1 -#pragma parameter FSR_FILMGRAIN "FSR LFGA Film Grain Intensity" 0.10 0.0 1.0 0.02 +#pragma parameter FSR_FILMGRAIN "FSR LFGA Film Grain Intensity" 0.3 0.0 2.0 0.02 +#pragma parameter FSR_GRAINCOLOR "FSR LFGA Film Grain Color: Gray | RGB" 1.0 0.0 1.0 1.0 +#pragma parameter FSR_GRAINPDF "FSR LFGA Grain PDF Curve (0.5 = Triangular, Lower = Gaussian)" 0.3 0.1 0.5 0.05 layout(push_constant) uniform Push { vec4 SourceSize; @@ -17,6 +20,8 @@ layout(push_constant) uniform Push { uint FrameCount; float FSR_SHARPENING; float FSR_FILMGRAIN; + float FSR_GRAINCOLOR; + float FSR_GRAINPDF; } params; layout(std140, set = 0, binding = 0) uniform UBO { @@ -45,14 +50,31 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define FSR_RCAS_F 1 AU4 con0; -AF4 FsrRcasLoadF(ASU2 p) { - return AF4(texelFetch(Source, ASU2(p), 0)); -} - +AF4 FsrRcasLoadF(ASU2 p) { return AF4(texelFetch(Source, p, 0)); } void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} #include "ffx_fsr1.h" +// prng: A simple but effective pseudo-random number generator [0;1[ +float prng(vec2 uv, float time) { + return fract(sin(dot(uv + fract(time), vec2(12.9898, 78.233))) * 43758.5453); +} + +// pdf: [-0.5;0.5[ +// Removes noise modulation effect by reshaping the uniform/rectangular noise +// distribution (RPDF) into a Triangular (TPDF) or Gaussian Probability Density +// Function (GPDF). +// shape = 1.0: Rectangular +// shape = 0.5: Triangular +// shape < 0.5: Gaussian (0.2~0.4) +float pdf(float noise, float shape) { + float orig = noise * 2.0 - 1.0; + noise = pow(abs(orig), shape); + noise *= sign(orig); + noise -= sign(orig); + return noise * 0.5; +} + void main() { FsrRcasCon(con0, params.FSR_SHARPENING); @@ -62,8 +84,17 @@ void main() { // FSR - [LFGA] LINEAR FILM GRAIN APPLICATOR if (params.FSR_FILMGRAIN > 0.0) { - AF1 noise = fract(10000 * sin(((vTexCoord.x + vTexCoord.y * A_2PI) * params.FrameCount))); - FsrLfgaF(Gamma2Color, AF3_(noise - 0.5), params.FSR_FILMGRAIN); + if (params.FSR_GRAINCOLOR == 0.0) { + float noise = pdf(prng(vTexCoord, params.FrameCount * 0.11), params.FSR_GRAINPDF); + FsrLfgaF(Gamma2Color, vec3(noise), params.FSR_FILMGRAIN); + } else { + vec3 rgbNoise = vec3( + pdf(prng(vTexCoord, params.FrameCount * 0.11), params.FSR_GRAINPDF), + pdf(prng(vTexCoord, params.FrameCount * 0.13), params.FSR_GRAINPDF), + pdf(prng(vTexCoord, params.FrameCount * 0.17), params.FSR_GRAINPDF) + ); + FsrLfgaF(Gamma2Color, rgbNoise, params.FSR_FILMGRAIN); + } } FragColor = vec4(Gamma2Color, 1.0); diff --git a/fsr/smaa+fsr.slangp b/fsr/smaa+fsr.slangp index 6eef148..ab33689 100644 --- a/fsr/smaa+fsr.slangp +++ b/fsr/smaa+fsr.slangp @@ -35,7 +35,14 @@ filter_linear5 = true scale_type5 = source scale5 = 1.0 -parameters = "SMAA_EDT;FSR_SHARPENING;FSR_FILMGRAIN" +parameters = "SMAA_EDT;SMAA_THRESHOLD;SMAA_MAX_SEARCH_STEPS;SMAA_MAX_SEARCH_STEPS_DIAG;SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR;SMAA_CORNER_ROUNDING;FSR_SHARPENING;FSR_FILMGRAIN;FSR_GRAINCOLOR;FSR_GRAINPDF" SMAA_EDT = 1.0 +SMAA_THRESHOLD = 0.05 +SMAA_MAX_SEARCH_STEPS = 40 +SMAA_MAX_SEARCH_STEPS_DIAG = 20 +SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR = 2.5 +SMAA_CORNER_ROUNDING = 50.0 FSR_SHARPENING = 0.1 -FSR_FILMGRAIN = 0.12 +FSR_FILMGRAIN = 0.3 +FSR_GRAINCOLOR = 1.0 +FSR_GRAINPDF = 0.3