[math-fun] Impossible triangle raytracer
Here's a neat visual trick: This shader program (by yx) renders a fully illuminated Reutersvard*/Penrose impossible triangle: https://www.shadertoy.com/view/ttXGWr All of the GLSL code used to generate the image on the left (minus Shadertoy's framework) is listed and editable on the right, and you can edit the code on the right to see what it does. Note how the geometry is locally consistent, and how the shadows between cubes, other cubes, and the ground all match up without any hard seams. Here's some context behind what makes this especially interesting. This program simulates global illumination using Monte Carlo path tracing: For each on- screen pixel, we trace a ray from a virtual camera into the scene, find the first place where the ray intersects the scene geometry, choose a new direction for the ray, trace the ray until it intersects the scene geometry again, and repeat until the ray reaches a light source (in this case, the sky) or reaches some maximum number of bounces (in this case, 4). (There's a lot I'm leaving out here, but this is sort of the basis behind it.) For geometry in R^3, this makes sense; finding ray-object intersections can sometimes be difficult, but are usually feasible. But here's the impossibility: how can you find the intersection of a ray and an object that can't exist? Left-click and drag over the image on the left (ideally while the shader is playing) to see a hint of how the shader works. *With a diaresis over the a: Reutersvärd --Neil Bickford (encoded partial solution (swaps a<->z): FromCharacterCode[219 - ToCharacterCode["zeviztv{tvlnvgib{levi{grnv"]].)
Neat trick! I wonder if there's a way to make it work with specular material, and maybe spheres and/or cylinders. Your simple trick probably won't work anymore but perhaps there is still a way to do it? Also, for some strange reason it doesn't render on my phone (or on my toaster oven but that's less surprising). -tom On Wed, May 8, 2019 at 9:06 PM Neil Bickford <techie314@gmail.com> wrote:
Here's a neat visual trick: This shader program (by yx) renders a fully illuminated Reutersvard*/Penrose impossible triangle: https://www.shadertoy.com/view/ttXGWr All of the GLSL code used to generate the image on the left (minus Shadertoy's framework) is listed and editable on the right, and you can edit the code on the right to see what it does. Note how the geometry is locally consistent, and how the shadows between cubes, other cubes, and the ground all match up without any hard seams.
Here's some context behind what makes this especially interesting. This program simulates global illumination using Monte Carlo path tracing: For each on- screen pixel, we trace a ray from a virtual camera into the scene, find the first place where the ray intersects the scene geometry, choose a new direction for the ray, trace the ray until it intersects the scene geometry again, and repeat until the ray reaches a light source (in this case, the sky) or reaches some maximum number of bounces (in this case, 4). (There's a lot I'm leaving out here, but this is sort of the basis behind it.)
For geometry in R^3, this makes sense; finding ray-object intersections can sometimes be difficult, but are usually feasible. But here's the impossibility: how can you find the intersection of a ray and an object that can't exist?
Left-click and drag over the image on the left (ideally while the shader is playing) to see a hint of how the shader works.
*With a diaresis over the a: Reutersvärd
--Neil Bickford
(encoded partial solution (swaps a<->z): FromCharacterCode[219 - ToCharacterCode["zeviztv{tvlnvgib{levi{grnv"]].) _______________________________________________ math-fun mailing list math-fun@mailman.xmission.com https://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
-- -- http://cube20.org/ -- http://golly.sf.net/ --
Hi Tom, It looks like replacing the diffuse material on the cubes with a mirror-like material in yx's shader works - there are some visual artifacts and this isn't particularly physically based, but replacing line 101 of Buffer A dir = B(gl_FragCoord.xyz/iResolution.xyz,n); with if(h.y<-T-.99) dir = B(gl_FragCoord.xyz/iResolution.xyz,n); else dir = dir - 2.0*dot(dir,n)*n; seems to work. Replacing the cubes with spheres, though (replace line 50 of Buffer A with d = max(d, length(p)-1.0);) does reveal the trick as expected in the reflections! I'm not sure either of a good way to handle this. --Neil Bickford
participants (2)
-
Neil Bickford -
Tomas Rokicki