Browse code

Add edge anti-aliasing

Robert Cranston authored on 27/10/2023 11:08:47
Showing 3 changed files

... ...
@@ -3,6 +3,7 @@
3 3
     { "include": ["@<glm/ext/(matrix|vector)_(float|u?int).*>", "public",  "<glm/glm.hpp>",                   "public"] },
4 4
     { "symbol":  ["glm::lookAt",                                "public",  "<glm/ext/matrix_transform.hpp>",  "public"] },
5 5
     { "symbol":  ["glm::perspective",                           "public",  "<glm/ext/matrix_clip_space.hpp>", "public"] },
6
+    { "symbol":  ["glm::project",                               "public",  "<glm/ext/matrix_projection.hpp>", "public"] },
6 7
     { "symbol":  ["glm::unProject",                             "public",  "<glm/ext/matrix_projection.hpp>", "public"] },
7 8
     { "symbol":  ["glm::convertLinearToSRGB",                   "public",  "<glm/gtc/color_space.hpp>",       "public"] },
8 9
 ]
9 10
Binary files a/doc/output.tga and b/doc/output.tga differ
... ...
@@ -56,6 +56,7 @@ struct Trace
56 56
 {
57 57
     float    distance;
58 58
     Material material;
59
+    vec3     miss;
59 60
 };
60 61
 
61 62
 //// Circle
... ...
@@ -69,15 +70,20 @@ struct Circle
69 70
         auto const offs = center - ray.origin;
70 71
         auto const proj = dot(offs, ray.direction);
71 72
         if (proj < 0.0F) // Past.
72
-            return {infinity, {}};
73
+            return {infinity, {}, {}};
73 74
         auto const perp2 = dot(offs, offs) - proj * proj;
74 75
         auto const pene2 = radius * radius - perp2;
75 76
         if (pene2 < 0.0F) // Miss.
76
-            return {infinity, {}};
77
+        {
78
+            auto const poin = ray.point(proj);
79
+            auto const rati = 1.0F - radius * inversesqrt(perp2);
80
+            auto const miss = rati * (center - poin);
81
+            return {proj, material, miss};
82
+        }
77 83
         auto const dist = proj - sqrt(pene2);
78 84
         if (dist < 0.0F) // Inside.
79
-            return {infinity, {}};
80
-        return {dist, material};
85
+            return {infinity, {}, {}};
86
+        return {dist, material, vec3(0.0F)};
81 87
     }
82 88
 };
83 89
 
... ...
@@ -91,7 +97,7 @@ struct Scene
91 97
     Shapes   shapes;
92 98
     Trace trace(Ray const & ray) const
93 99
     {
94
-        auto nearest = Trace{infinity, background};
100
+        auto nearest = Trace{infinity, background, {}};
95 101
         for (auto const & shape : shapes)
96 102
         {
97 103
             auto const trace = shape.trace(ray);
... ...
@@ -122,6 +128,16 @@ struct Camera
122 128
         auto const direction = normalize(world.xyz() - position);
123 129
         return Ray{position, direction};
124 130
     }
131
+    vec2 project(uvec2 const & size, vec3 const & point) const
132
+    {
133
+        auto const aspect   = (float)size.x / (float)size.y;
134
+        auto const viewport = uvec4(0, 0, size);
135
+        auto const up       = vec3(0.0F, 1.0F, 0.0F);
136
+        auto const view     = glm::lookAt(position, target, up);
137
+        auto const proj     = glm::perspective(fovy, aspect, near, far);
138
+        auto const window   = glm::project(point, view, proj, viewport);
139
+        return window.xy();
140
+    }
125 141
 };
126 142
 
127 143
 //// ACES
... ...
@@ -220,6 +236,15 @@ int main(int argc, char const * argv[])
220 236
         {
221 237
             auto trace = scene.trace(ray);
222 238
             auto color = trace.material.color;
239
+            if (trace.miss != vec3(0.0F))
240
+            {
241
+                auto const point = ray.point(trace.distance);
242
+                auto const dist  = distance(
243
+                    camera.project(size, point),
244
+                    camera.project(size, point + trace.miss)
245
+                );
246
+                color.a *= 1.0F - clamp(dist, 0.0F, 1.0F);
247
+            }
223 248
             rgb   += color.rgb() * color.a * trans;
224 249
             trans *= 1.0F - color.a;
225 250
             if (trace.distance == infinity || trans == 0.0F)