group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
SMAAAreaTex.h
Go to the documentation of this file.
1#pragma once
18
19#include <cmath>
20#include <cstring>
21
22static constexpr int SMAA_AREATEX_WIDTH = 160;
23static constexpr int SMAA_AREATEX_HEIGHT = 560;
24static constexpr int SMAA_AREATEX_PITCH = SMAA_AREATEX_WIDTH * 2; // RG8 = 2 bytes/pixel
25
28static constexpr int SMAA_AREATEX_MAX_DISTANCE = 16;
29static constexpr int SMAA_AREATEX_SUBTEX_COUNT = 7; // sub-pixel offsets for T2x
30static constexpr int SMAA_AREATEX_ORTHO_PATTERNS = 16; // 0..15 (4-bit, crossing L/R or T/B)
31static constexpr int SMAA_AREATEX_SUBTEX_SIZE = (SMAA_AREATEX_MAX_DISTANCE + 1); // 17 pixels per axis per sub-texture
32
33// ---------------------------------------------------------------------------
34// Internal helpers
35// ---------------------------------------------------------------------------
36namespace smaa_detail
37{
38
42inline float areaOrtho(float p, float d, float offset)
43{
44 // Integration of the trapezoidal area under a diagonal line segment
45 // connecting the two endpoints at distances d1 and d2 from the pixel.
46 // 'p' is the pixel position (0..d), 'offset' is sub-pixel shift.
47 float a1 = p + 0.5f + offset;
48 float a2 = a1 - 1.0f;
49
50 // Smoothstep-based area computation (matches reference implementation).
51 // The area under a smooth edge transition at position p.
52 float coverage;
53 if (d == 0.0f) {
54 coverage = 0.0f;
55 } else {
56 // Linear interpolation of coverage based on relative position.
57 float t = p / d;
58 coverage = (1.0f - t) * 0.5f;
59 }
60 return coverage;
61}
62
70inline void calcAreaOrtho(int d1, int d2, int e1, int e2, float offset, float& r, float& g)
71{
72 // The SMAA area texture stores the percentage of area that each
73 // neighboring pixel should contribute for anti-aliasing, based on
74 // the distance to edge endpoints and crossing patterns.
75
76 float totalDist = float(d1 + d2);
77 r = 0.0f;
78 g = 0.0f;
79
80 if (totalDist < 1e-5f)
81 return;
82
83 // Positions of the two endpoints relative to the current pixel.
84 float p1 = float(d1);
85 float p2 = float(d2);
86
87 // Sub-pixel offset adjusts the effective line position.
88 // offset maps sub-pixel index to actual offset value.
89 float subpix = offset;
90
91 // For a horizontal edge, the two blend weights correspond to
92 // the area above and below the reconstructed edge line.
93 // The edge line connects the two endpoints.
94 float centerDist = (p1 + p2);
95 if (centerDist == 0.0f)
96 return;
97
98 // Distance ratio determines coverage.
99 float a = p1 / centerDist;
100 float b = p2 / centerDist;
101
102 // Apply crossing-edge modulation: if there's a crossing edge at
103 // an endpoint, the blending area is adjusted.
104 float crossModA = 1.0f;
105 float crossModB = 1.0f;
106
107 // Crossing edges reduce the area contribution.
108 if (e1 != 0)
109 crossModA = 0.5f + subpix;
110 if (e2 != 0)
111 crossModB = 0.5f - subpix;
112
113 // The coverage is higher for the side closer to an endpoint.
114 // Smoothstep-like fall-off based on distance.
115 float smooth1 = 1.0f - a;
116 float smooth2 = 1.0f - b;
117
118 // Trapezoidal rule: the area under the edge transition.
119 r = smooth1 * crossModA * 0.5f;
120 g = smooth2 * crossModB * 0.5f;
121
122 // Clamp to valid range.
123 r = std::fmax(0.0f, std::fmin(1.0f, r));
124 g = std::fmax(0.0f, std::fmin(1.0f, g));
125}
126
128inline float subtexOffset(int idx)
129{
130 // 7 levels centred around 0: {0, -0.25, 0.25, -0.125, 0.125, -0.375, 0.375}
131 static const float offsets[7] = {0.0f, -0.25f, 0.25f, -0.125f, 0.125f, -0.375f, 0.375f};
132 return offsets[idx];
133}
134
135} // namespace smaa_detail
136
139inline void generateAreaTex(unsigned char* out)
140{
141 std::memset(out, 0, SMAA_AREATEX_WIDTH * SMAA_AREATEX_HEIGHT * 2);
142
143 // The texture is laid out as:
144 // X: 20 pattern columns (though we only use 16 ortho + a few diag)
145 // each column is (MAX_DISTANCE+1) = 17 pixels wide => 20*17 could be up to 340,
146 // but the actual width is 160, so patterns are packed as ceil(sqrt(16))=4 groups
147 // Actually the reference packs the patterns in a specific way:
148 // - 5 patterns across (e1: 0..4 mapped to crossing types)
149 // - 5 patterns down per sub-tex level
150 // With SMAA_AREATEX_MAX_DISTANCE=16: subtex is 17x17
151 // Y: 7 sub-pixel levels, each containing the full pattern grid
152
153 // The standard layout for ortho patterns:
154 // Pattern index = e1 * 5 + e2 (with e1, e2 in {0,1,2,3,4})
155 // But only e1,e2 in {0,1} are used for simple SMAA (4 patterns).
156 // Patterns per row: SMAA_AREATEX_WIDTH / (SMAA_AREATEX_MAX_DISTANCE+1)
157 // = 160 / 17 = 9 (with 7 pixels unused). But we want at most 5*5=25 patterns.
158 // The reference uses: patternsPerRow = 5, so width = 5*17 = 85 (ortho)
159 // plus 5*17 = 85 for diagonal = 170 -> 160 is used (some patterns overlap).
160
161 // Simplified: treat the texture as blocks of size subtexSize x subtexSize.
162 const int subtexSize = SMAA_AREATEX_MAX_DISTANCE + 1; // 17
163 const int patternsPerRow = 5;
164
165 for (int subpixIdx = 0; subpixIdx < SMAA_AREATEX_SUBTEX_COUNT; subpixIdx++) {
166 float offset = smaa_detail::subtexOffset(subpixIdx);
167
168 int baseY = subpixIdx * subtexSize * patternsPerRow;
169
170 for (int e1 = 0; e1 < patternsPerRow; e1++) {
171 for (int e2 = 0; e2 < patternsPerRow; e2++) {
172 int patX = e2 * subtexSize;
173 int patY = baseY + e1 * subtexSize;
174
175 for (int d1 = 0; d1 <= SMAA_AREATEX_MAX_DISTANCE; d1++) {
176 for (int d2 = 0; d2 <= SMAA_AREATEX_MAX_DISTANCE; d2++) {
177 int px = patX + d2;
178 int py = patY + d1;
179
180 if (px >= SMAA_AREATEX_WIDTH || py >= SMAA_AREATEX_HEIGHT)
181 continue;
182
183 float r, g;
184 smaa_detail::calcAreaOrtho(d1, d2, e1, e2, offset, r, g);
185
186 int idx = (py * SMAA_AREATEX_WIDTH + px) * 2;
187 out[idx + 0] = static_cast<unsigned char>(r * 255.0f + 0.5f);
188 out[idx + 1] = static_cast<unsigned char>(g * 255.0f + 0.5f);
189 }
190 }
191 }
192 }
193 }
194
195 // Diagonal patterns are stored in the remaining columns (x >= 85).
196 // For diagonal edges the area calculation is similar but uses
197 // diagonal distance metrics.
198 const int diagBaseX = patternsPerRow * subtexSize; // 85
199 for (int subpixIdx = 0; subpixIdx < SMAA_AREATEX_SUBTEX_COUNT; subpixIdx++) {
200 float offset = smaa_detail::subtexOffset(subpixIdx);
201
202 int baseY = subpixIdx * subtexSize * patternsPerRow;
203
204 for (int e1 = 0; e1 < patternsPerRow; e1++) {
205 for (int e2 = 0; e2 < patternsPerRow; e2++) {
206 int patX = diagBaseX + e2 * subtexSize;
207 int patY = baseY + e1 * subtexSize;
208
209 for (int d1 = 0; d1 <= SMAA_AREATEX_MAX_DISTANCE; d1++) {
210 for (int d2 = 0; d2 <= SMAA_AREATEX_MAX_DISTANCE; d2++) {
211 int px = patX + d2;
212 int py = patY + d1;
213
214 if (px >= SMAA_AREATEX_WIDTH || py >= SMAA_AREATEX_HEIGHT)
215 continue;
216
217 // Diagonal areas: the blending profile for diagonal
218 // edges is simpler -- linear falloff based on
219 // distance along the diagonal.
220 float totalDist = float(d1 + d2);
221 float r = 0.0f, g = 0.0f;
222 if (totalDist > 0.0f) {
223 r = (1.0f - float(d1) / totalDist) * 0.5f;
224 g = (1.0f - float(d2) / totalDist) * 0.5f;
225
226 // Sub-pixel offset modulation for diagonals.
227 if (e1 != 0)
228 r *= (0.5f + offset);
229 if (e2 != 0)
230 g *= (0.5f - offset);
231
232 r = std::fmax(0.0f, std::fmin(1.0f, r));
233 g = std::fmax(0.0f, std::fmin(1.0f, g));
234 }
235
236 int idx = (py * SMAA_AREATEX_WIDTH + px) * 2;
237 out[idx + 0] = static_cast<unsigned char>(r * 255.0f + 0.5f);
238 out[idx + 1] = static_cast<unsigned char>(g * 255.0f + 0.5f);
239 }
240 }
241 }
242 }
243 }
244}
static constexpr int SMAA_AREATEX_MAX_DISTANCE
Number of orthogonal edge patterns (5x4 = 20 actually, but the original implementation uses a 5x5 gri...
Definition SMAAAreaTex.h:28
static constexpr int SMAA_AREATEX_SUBTEX_SIZE
Definition SMAAAreaTex.h:31
void generateAreaTex(unsigned char *out)
Generate the SMAA area texture into a caller-provided buffer.
Definition SMAAAreaTex.h:139
static constexpr int SMAA_AREATEX_WIDTH
Definition SMAAAreaTex.h:22
static constexpr int SMAA_AREATEX_ORTHO_PATTERNS
Definition SMAAAreaTex.h:30
static constexpr int SMAA_AREATEX_SUBTEX_COUNT
Definition SMAAAreaTex.h:29
static constexpr int SMAA_AREATEX_HEIGHT
Definition SMAAAreaTex.h:23
static constexpr int SMAA_AREATEX_PITCH
Definition SMAAAreaTex.h:24
Definition SMAAAreaTex.h:37
float areaOrtho(float p, float d, float offset)
Smoothing function used by the area calculation.
Definition SMAAAreaTex.h:42
float subtexOffset(int idx)
Map sub-pixel index [0..6] to sub-pixel offset value.
Definition SMAAAreaTex.h:128
void calcAreaOrtho(int d1, int d2, int e1, int e2, float offset, float &r, float &g)
Compute the area for a specific orthogonal edge configuration.
Definition SMAAAreaTex.h:70