I have a floor node, on which I need to cast shadow from directional light. This node needs to be transparent (used in AR environment)
It's been awhile since this was posted but maybe someone will find this alternative solution useful. I encountered a similar situation and what I ended up doing was rendering using multiple passes via SCNTechnique. First I rendered a floor with a solid white diffuse and then I rendered the rest of the scene without the floor. To do this I set the categoryBitMask of my SCNFloor to 3 and left the others with the default value of 1.
Next I created my SCNTechnique with this definition which renders the floor and the rest of the scene into separate buffers and then combines them together into the final scene:
self.sceneView.technique = SCNTechnique(dictionary: [
"passes" : [
"store-floor": [
"draw" : "DRAW_NODE",
"node" : "floor-node",
"inputs" : [],
"outputs" : [ "color" : "color_floor" ]
],
"store-scene": [
"draw" : "DRAW_SCENE",
"excludeCategoryMask" : 2,
"inputs" : [],
"outputs" : [ "color" : "color_scene" ]
],
"recall-scene": [
"draw" : "DRAW_QUAD",
"metalVertexShader" : "vertex_tecnique_basic",
"metalFragmentShader" : "fragment_tecnique_merge",
"inputs" : [ "alphaTex" : "color_floor", "sceneTex" : "color_scene" ],
"outputs" : [ "color" : "COLOR" ]
]
],
"symbols" : [
"vertexSymbol" : [ "semantic" : "vertex" ]
],
"targets" : [
"color_floor" : [ "type" : "color" ],
"color_scene" : [ "type" : "color" ],
],
"sequence" : [
"store-floor",
"store-scene",
"recall-scene"
]
])
Next the Metal share code that takes those two buffers and combines them together where the alpha value ranges from 0 for white to 1 for black.
using namespace metal;
#include
struct TechniqueVertexIn
{
float4 position [[attribute(SCNVertexSemanticPosition)]];
};
struct TechniqueVertexOut
{
float4 framePos [[position]];
float2 centeredLoc;
};
constexpr sampler s = sampler(coord::normalized, address::repeat, filter::linear);
vertex TechniqueVertexOut vertex_tecnique_basic(
TechniqueVertexIn in [[stage_in]],
constant SCNSceneBuffer& scnFrame [[buffer(0)]])
{
TechniqueVertexOut vert;
vert.framePos = float4(in.position.x, in.position.y, 0.0, 1.0);
vert.centeredLoc = float2((in.position.x + 1.0) * 0.5 , (in.position.y + 1.0) * -0.5);
return vert;
}
fragment half4 fragment_tecnique_merge(
TechniqueVertexOut vert [[stage_in]],
texture2d alphaTex [[texture(0)]],
texture2d sceneTex [[texture(1)]])
{
float4 alphaColor = alphaTex.sample(s, vert.centeredLoc);
float4 sceneColor = sceneTex.sample(s, vert.centeredLoc);
float alpha = 1.0 - max(max(alphaColor.r, alphaColor.g), alphaColor.b); // since floor should be white, could just pick a chan
alpha *= alphaColor.a;
alpha = max(sceneColor.a, alpha);
return half4(half3(sceneColor.rgb * alpha), alpha);
}
Lastly here's an example of what that ends up looking like with all the pieces put together.