... | ... |
@@ -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 |
} |