Browse code

Add transparency

Robert Cranston authored on 27/10/2023 11:08:02
Showing 2 changed files

1 1
Binary files a/doc/output.tga and b/doc/output.tga differ
... ...
@@ -25,6 +25,7 @@ using namespace glm;
25 25
 /// Constants
26 26
 
27 27
 auto const infinity = std::numeric_limits<float>::infinity();
28
+auto const delta    = 0.001F;
28 29
 
29 30
 
30 31
 /// Types
... ...
@@ -34,12 +35,20 @@ struct Ray
34 35
 {
35 36
     vec3 origin;
36 37
     vec3 direction;
38
+    vec3 point(float distance) const
39
+    {
40
+        return origin + direction * distance;
41
+    }
42
+    Ray resumed(float distance)
43
+    {
44
+        return {point(distance), direction};
45
+    }
37 46
 };
38 47
 
39 48
 //// Material
40 49
 struct Material
41 50
 {
42
-    vec3 color;
51
+    vec4 color;
43 52
 };
44 53
 
45 54
 //// Trace
... ...
@@ -191,24 +200,34 @@ int main(int argc, char const * argv[])
191 200
     };
192 201
     auto const scene = Scene{
193 202
         // background
194
-        {vec3(0.2F, 0.2F, 0.5F)},
203
+        {vec4(0.2F, 0.2F, 0.5F, 0.5F)},
195 204
         // shapes
196 205
         {
197
-            {vec3( 2.0F, -1.0F, -10.0F), 3.0F, {vec3(1.0F, 0.0F, 0.0F)}},
198
-            {vec3( 1.0F,  2.0F,  -7.0F), 2.0F, {vec3(0.0F, 1.0F, 0.0F)}},
199
-            {vec3(-1.0F,  0.0F,  -4.0F), 1.0F, {vec3(0.0F, 0.0F, 1.0F)}},
200
-            {vec3( 0.0F, -1.0F,  -3.0F), 0.2F, {vec3(0.0F, 1.0F, 1.0F)}},
206
+            {vec3( 2.0F, -1.0F, -10.0F), 3.0F, {vec4(1.0F, 0.0F, 0.0F, 1.0F)}},
207
+            {vec3( 1.0F,  2.0F,  -7.0F), 2.0F, {vec4(0.0F, 1.0F, 0.0F, 1.0F)}},
208
+            {vec3(-1.0F,  0.0F,  -4.0F), 1.0F, {vec4(0.0F, 0.0F, 1.0F, 1.0F)}},
209
+            {vec3( 0.0F, -1.0F,  -3.0F), 0.2F, {vec4(0.0F, 1.0F, 1.0F, 0.5F)}},
201 210
         },
202 211
     };
203 212
     auto const tonemap = ACES{vec3(1.0F)};
204 213
     auto const output  = TGA{uvec2(640, 480), path};
205 214
     //// Render
206 215
     output.render([&](uvec2 const & size, uvec2 const & pixel) {
207
-        auto const ray   = camera.ray(size, pixel);
208
-        auto const trace = scene.trace(ray);
209
-        auto const rgb   = trace.material.color;
210
-        auto const srgb  = convertLinearToSRGB(tonemap.transform(rgb));
211
-        auto const alpha = 1.0F;
216
+        auto rgb   = vec3(0.0F); // Pre-multiplied alpha (opacity).
217
+        auto trans = 1.0F;       // 1 - alpha (opacity).
218
+        auto ray   = camera.ray(size, pixel);
219
+        while (true)
220
+        {
221
+            auto trace = scene.trace(ray);
222
+            auto color = trace.material.color;
223
+            rgb   += color.rgb() * color.a * trans;
224
+            trans *= 1.0F - color.a;
225
+            if (trace.distance == infinity || trans == 0.0F)
226
+                break;
227
+            ray = ray.resumed(trace.distance + delta);
228
+        }
229
+        auto const alpha = 1.0F - trans;
230
+        auto const srgb  = convertLinearToSRGB(tonemap.transform(rgb / alpha));
212 231
         return vec4(srgb, alpha);
213 232
     });
214 233
 }