我是Metal(和一般着色器)的新手。我一直在尝试使用ARSCNView
和MSL spec创建一个SCNTechnique docs应用程序以应用着色器。
我想要一个着色器管道,它将使我仅更改摄影机提要视图(sceneView.scene.background
),但允许所有SCNNodes与重叠的未更改摄影机提要混合。这是我的计划:
[1)第一遍将我的第一个样式化着色器应用于场景(它只是调整颜色/亮度,我已经用DRAW_QUAD
对其进行了测试并且可以正常工作)到DRAW_SCENE
,并使用excludeCategoryMask
排除所有节点。
着色器应包括某种统一的数据结构,该结构包含场景中的所有其他节点(当前为空,因为尚未渲染节点),并使用其屏幕空间坐标在滤色器中剪切适当大小/位置的形状节点重叠的位置。
[2)第二遍使用标准/默认SCNKit着色器使用DRAW_NODE
渲染其余节点(球体等)。
我不知道这是否是一种有效的方法,因为我的应用几乎在com.apple.scenekit.scnview-renderer (15): EXC_BAD_ACCESS (code=1, address=0xeb52be860)
下崩溃。当我从DRAW_QUAD
切换到DRAW_SCENE
时,着色器崩溃。我想我缺少深度缓冲之类的东西。
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct VertexInput_0 {
float4 position [[ attribute(SCNVertexSemanticPosition) ]];
float2 texcoord [[ attribute(SCNVertexSemanticTexcoord0) ]];
};
struct VertexOutput_0 {
float4 position [[position]];
float2 texcoord;
};
// metalVertexShader
vertex VertexOutput_0 scene_filter_vertex_0(VertexInput_0 in [[stage_in]])
{
VertexOutput_0 out;
out.position = in.position;
out.texcoord = float2((in.position.x + 1.0) * 0.5 , (in.position.y + 1.0) * -0.5);
return out;
}
// metalFragmentShader
fragment half4 scene_filter_fragment_0(VertexOutput_0 vert [[stage_in]],
texture2d<half, access::sample> scene [[texture(0)]])
{
constexpr sampler samp = sampler(coord::normalized, address::repeat, filter::nearest);
half4 color = scene.sample(samp, vert.texcoord);
constexpr half3 weights = half3(2, 0.7152, 0.0722);
color.rgb = half3(dot(color.rgb, weights));
return color;
}
// Doesn't reach here, crashes before second pass below
struct VertexInput_1 {
float4 position [[ attribute(SCNVertexSemanticPosition) ]];
float2 texcoord [[ attribute(SCNVertexSemanticTexcoord0) ]];
};
struct VertexOutput_1 {
float4 position [[position]];
float2 texcoord;
};
// metalVertexShader
vertex VertexOutput_1 scene_filter_vertex_1(VertexInput_1 in [[stage_in]])
{
VertexOutput_1 out;
out.position = in.position;
out.texcoord = float2((in.position.x + 1.0) * 0.5 , (in.position.y + 1.0) * -0.5);
return out;
}
// metalFragmentShader
fragment half4 scene_filter_fragment_1(VertexOutput_1 vert [[stage_in]],
texture2d<half, access::sample> scene [[texture(0)]])
{
constexpr sampler samp = sampler(coord::normalized, address::repeat, filter::nearest);
half4 color = scene.sample(samp, vert.texcoord);
return color;
}
<plist version="1.0">
<dict>
<key>sequence</key>
<array>
<string>filter_0</string>
<string>filter_1</string>
</array>
<key>passes</key>
<dict>
<key>filter_1</key>
<dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
<key>inputs</key>
<dict>
<key>scene</key>
<string>COLOR</string>
</dict>
<key>draw</key>
<string>DRAW_QUAD</string>
<key>metalVertexShader</key>
<string>scene_filter_vertex_2</string>
<key>metalFragmentShader</key>
<string>scene_filter_fragment_2</string>
</dict>
<key>filter_0</key>
<dict>
<key>metalFragmentShader</key>
<string>scene_filter_fragment_0</string>
<key>metalVertexShader</key>
<string>scene_filter_vertex_0</string>
<key>excludeCategoryMask</key>
<integer>2</integer>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
<key>inputs</key>
<dict>
<key>scene</key>
<string>COLOR</string>
</dict>
<key>draw</key>
<string>DRAW_SCENE</string>
</dict>
</dict>
</dict>
</plist>
为什么会崩溃?我在某处缺少参数吗?
可能是scene_filter_vertex_2
,并且scene_filter_fragment_2
需要重命名scene_filter_vertex_1
和scene_filter_fragment_1