There is nothing more exciting in programming than designing a graphics application. Thankfully, there is one person on Github Garrett Johnson, who implemented a path-tracing algorithm on top of the well-known THREE.js graphics engine. Moreover, it fully supports features from the original library and can be anytime flipped as a main renderer.
I hooked up his library to works as a secondary engine for Graphics3D
function presented in wljs-graphics3d-threejs library. Just pass an option
Graphics3D[%, "RTX"->True]
And it will bake a realtime photorealistic image. It also supports all properties used in traditional rendering, i.e. Emissive[]
, Metallness[]
, HDRI map and many more!
Some classical examples from Wolfram Mathematica
You might recognize those examples from Graphics3D
official documentation page. Here is some other neat pictures produced using the following code
Metallic maze
This was taken from the discussion here. The maze is made from many polygons, where for the surface Metallness[1], Roughness[0]
were applied. Since it provides perfect reflection, the overall time for rendering (when the noise has gone) is relatively low.
showmaze = Uncompress[FromCharacterCode @@ ImageData[Import["https://i.stack.imgur.com/XVJcP.png"], "Byte"]];
prims = CapsuleShape @@@ Cases[showmaze, _Cylinder, Infinity];
prims = prims /. {{5., 5., 5.} -> {5.5, 5., 5.}, {1., 1., 1.} -> {1., 0.5, 1.}};
ims = RegionImage[#, {{0.3`, 5.7`}, {0.3`, 5.7`}, {0.3`, 5.7`}}, RasterSize -> 100] & /@ prims;
im = ImageApply[Max, ims];
Then, the generated mesh is lit by lighting
arrays, which contain randomly distributed glowing spheres
lighting = Table[{Emissive[RGBColor@@(RandomReal[{0,1}, 3]), 2], Sphere[RandomReal[{1,92}, 3], RandomReal[{1,7}]]}, {i, 1, 30}];
Show[bmr = ImageMesh[im, Method -> "DualMarchingCubes"], PlotRange -> {{0, 91}, {1, 92}, {0, 91}}][[1]];
Graphics3D[{lighting, Metalness[0], Roughness[0], %}, "Lighting"->None, ViewProjection->"Perspective", "RTX"->True]
Despite the complicity of the scene, it renders in real time with an acceptable amount of noise.
Torus Knot
This is rather classical example, but uses a glossy surface using Roughness[0]
lit by two glowing spheres
KnotData[{"TorusKnot", {3, 5}}][[1]];
Graphics3D[{{Emissive[Red, 5], Sphere[{0,0,-0.1}, 0.14]}, {Roughness[0],Cyan, %}, {Emissive[RGBColor[{1,1,1}], 5], Sphere[{0,0,0.4}, 0.1]}}, Lighting->None, "RTX"->True]
Here is the result
Looks like a dream...
Limitations
- The dynamic scenes now are not supported, but can be added in theory according to the documentation of the path-rendering library.
- Requires a dedicated GPU (actually with my Intel UHD integrated graphics it works, but demands an extremely long time to compile shaders to start rendering). However, iPhones, Androids can still handle not very complicated scenes.
- Safari crashes (Firefox, Chrome, Vivaldi work well)