• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef SHADERS_COMMON_FXAA_REFERENCE_H
17 #define SHADERS_COMMON_FXAA_REFERENCE_H
18 
19 #define FXAA_USE_PATCHES 1
20 
21 // prefer high quality
22 #define FXAA_QUALITY 29
23 
24 /**
25  * Based on the NVIDIA FXAA 3.11 reference implementation  by TIMOTHY LOTTES
26  * See: https://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
27  */
28 
29 // integration settings
30 #ifndef FXAA_USE_PATCHES
31 #define FXAA_USE_PATCHES 0
32 #endif
33 
34 #ifndef FXAA_LUMA_GREEN
35 #define FXAA_LUMA_GREEN 0
36 #endif
37 
38 #define FxaaTexTop(t, s, p) textureLod(sampler2D(t, s), p, 0.0)
39 #define FxaaTexOff(t, s, p, o, r) textureLodOffset(sampler2D(t, s), p, 0.0, o)
40 
41 #if (FXAA_LUMA_GREEN == 0)
FxaaCompLuma(vec4 rgba)42 float FxaaCompLuma(vec4 rgba)
43 {
44     return rgba.w;
45 }
46 #else
FxaaCompLuma(vec4 rgba)47 float FxaaCompLuma(vec4 rgba)
48 {
49     return rgba.y;
50 }
51 #endif
52 
FxaaPixelShader(vec2 fragCoord,vec4 neighborCoords,texture2D texture,sampler samp,vec2 invFrameSize,vec4 invFrameOpt,vec4 invFrameOpt2,vec4 console360InvFrameOpt2,float subpixelQuality,float edgeThresholdQuality,float edgeThresholdMinQuality,float edgeSharpness,float edgeThreshold,float edgeThresholdMin,vec4 console360ConstDir)53 vec4 FxaaPixelShader(vec2 fragCoord, vec4 neighborCoords, texture2D texture, sampler samp, vec2 invFrameSize,
54     vec4 invFrameOpt, vec4 invFrameOpt2, vec4 console360InvFrameOpt2, float subpixelQuality, float edgeThresholdQuality,
55     float edgeThresholdMinQuality, float edgeSharpness, float edgeThreshold, float edgeThresholdMin,
56     vec4 console360ConstDir)
57 {
58     const float lumaNw = FxaaCompLuma(FxaaTexTop(texture, samp, neighborCoords.xy));
59     const float lumaSw = FxaaCompLuma(FxaaTexTop(texture, samp, neighborCoords.xw));
60     float lumaNe = FxaaCompLuma(FxaaTexTop(texture, samp, neighborCoords.zy));
61     const float lumaSe = FxaaCompLuma(FxaaTexTop(texture, samp, neighborCoords.zw));
62 
63     // current pixel's color and luminance
64     const vec4 colorM = FxaaTexTop(texture, samp, fragCoord.xy);
65 
66 #if (FXAA_LUMA_GREEN == 0)
67     const float lumaM = colorM.w;
68 #else
69     const float lumaM = colorM.y;
70 #endif
71 
72     // min-max luminance around the pixel
73     const float lumaMaxNwSw = max(lumaNw, lumaSw);
74 #if FXAA_USE_PATCHES == 0
75     lumaNe += 1.0 / 384.0;
76 #endif
77     const float lumaMinNwSw = min(lumaNw, lumaSw);
78     const float lumaMaxNeSe = max(lumaNe, lumaSe);
79     const float lumaMinNeSe = min(lumaNe, lumaSe);
80     const float lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
81     const float lumaMin = min(lumaMinNeSe, lumaMinNwSw);
82 
83     const float lumaMaxScaled = lumaMax * edgeThreshold;
84 
85     const float lumaMinM = min(lumaMin, lumaM);
86     const float lumaMaxScaledClamped = max(edgeThresholdMin, lumaMaxScaled);
87 
88     const float lumaMaxM = max(lumaMax, lumaM);
89 
90     // edge direction
91     float dirSwMinusNe = lumaSw - lumaNe;
92 #if FXAA_USE_PATCHES
93     dirSwMinusNe += 1.0 / 512.0;
94 #endif
95 
96     const float lumaRange = lumaMaxM - lumaMinM;
97     const float dirSeMinusNw = lumaSe - lumaNw;
98 
99     if (lumaRange < lumaMaxScaledClamped) {
100         return colorM;
101     }
102 
103     vec2 edgeDir;
104     edgeDir.x = dirSwMinusNe + dirSeMinusNw;
105     edgeDir.y = dirSwMinusNe - dirSeMinusNw;
106     const vec2 normEdgeDir = normalize(edgeDir.xy);
107 
108     // sample colors along the edge
109     const vec4 colorN1 = FxaaTexTop(texture, samp, fragCoord.xy - normEdgeDir * invFrameOpt.zw);
110     const vec4 colorP1 = FxaaTexTop(texture, samp, fragCoord.xy + normEdgeDir * invFrameOpt.zw);
111 
112 #if FXAA_USE_PATCHES
113     const float dirAbsMinTimesC = max(abs(normEdgeDir.x), abs(normEdgeDir.y)) * edgeSharpness * 0.015;
114     const vec2 scaledEdgeDir = normEdgeDir.xy * min(lumaRange / dirAbsMinTimesC, 3);
115 #else
116     const float dirAbsMinTimesC = min(abs(normEdgeDir.x), abs(normEdgeDir.y)) * edgeSharpness;
117     const vec2 scaledEdgeDir = clamp(normEdgeDir.xy / dirAbsMinTimesC, -2, 2);
118 #endif
119 
120     const vec4 colorN2 = FxaaTexTop(texture, samp, fragCoord.xy - scaledEdgeDir * invFrameOpt2.zw);
121     const vec4 colorP2 = FxaaTexTop(texture, samp, fragCoord.xy + scaledEdgeDir * invFrameOpt2.zw);
122 
123     const vec4 blendedA = colorN1 + colorP1;
124     vec4 blendedB = ((colorN2 + colorP2) * 0.25) + (blendedA * 0.25);
125 
126 #if (FXAA_LUMA_GREEN == 0)
127     const bool useTwoTap = (blendedB.w < lumaMin) || (blendedB.w > lumaMax);
128 #else
129     const bool useTwoTap = (blendedB.y < lumaMin) || (blendedB.y > lumaMax);
130 #endif
131     if (useTwoTap) {
132         blendedB.xyz = blendedA.xyz * 0.5;
133     }
134 
135 #if FXAA_USE_PATCHES
136     blendedB = mix(blendedB, colorM, 0.25);
137 #endif
138     return blendedB;
139 }
140 
141 #endif // SHADERS_COMMON_FXAA_REFERENCE_H
142