Showing a shadow on a transparent floor/plane in scenekit

metal, opengl-es-2.0, scenekit

Solution

Ok, so check out this example project on Github:

https://github.com/carolight/Metal-Shadow-Map/blob/master/Shadows/Shader.metal#L67

That link is to the shader that performs the shadow map testing. Basically, it normalizes the Z position of the fragment being rendered and compares it to the Z-Buffer of the shadow map. If it is less than the shadow-Z, the pixel is fully lit (line 67) else it is tinted slightly (line 69).

What you want to do instead is write (0,0,0, shadow_opacity) for line 69 and (0,0,0,0) for line 67. This should emit transparent pixels. Set shadow_opacity as a uniform from [0.0..1.0].

The rest of the setup is shown in the example. Tilt the plane/camera to the desired setting, skip drawing the cube/vase/whatever in the `main pass` if you don't really want it in the scene (line 279). (However, note the `shadow pass` and keep it there).

Problem

trying to figure out how I can render a shadow on an invisible plane, so the background of my `sceneView` shows through. THREE.js has a `ShadowMaterial` which does exactly this - only the shadow is rendered. Current thinking is to make a custom Metal shader which looks straightforward, but i'm unsure how to go about knocking out the floor to show everything aside from the shadow. Here's an example of a shadow catcher: https://knowledge.autodesk.com/search-result/caas/sfdcarticles/sfdcarticles/Maya-2015-Shadow-Catching-with-Use-Background-material.html

Original source