Scenekit 基于顶点世界位置Y坐标修改金属碎片着色

Scenekit 基于顶点世界位置Y坐标修改金属碎片着色,scenekit,metal,fragment-shader,scntechnique,Scenekit,Metal,Fragment Shader,Scntechnique,我试图使用一个带有SCNTechnique的金属碎片着色器,根据顶点Y世界位置修改碎片颜色 到目前为止我的理解是 SCNTechnique可以配置一系列渲染过程。渲染过程允许注入顶点和片段着色器。这些着色器是用金属编写的。描述了这两个系统支持哪些输入/输出。 将为正在渲染的每个顶点调用顶点着色器。我们可以将其他信息从顶点着色器传递到片段着色器(如3D空间中的位置,请参见)。 片段着色器最接近一个像素,如果有多个三角形“符合”该像素,则可以称为单个“像素”的时间倍数。(通常)碎片着色后,如果碎片未

我试图使用一个带有SCNTechnique的金属碎片着色器,根据顶点Y世界位置修改碎片颜色

到目前为止我的理解是 SCNTechnique可以配置一系列渲染过程。渲染过程允许注入顶点和片段着色器。这些着色器是用金属编写的。描述了这两个系统支持哪些输入/输出。 将为正在渲染的每个顶点调用顶点着色器。我们可以将其他信息从顶点着色器传递到片段着色器(如3D空间中的位置,请参见)。 片段着色器最接近一个像素,如果有多个三角形“符合”该像素,则可以称为单个“像素”的时间倍数。(通常)碎片着色后,如果碎片未通过深度或模板测试,则可能会丢弃碎片

我所尝试的 这就是我所尝试的。(我希望这能说明我的理解不足之处)

struct VertexOut{
浮动4位[[位]];
};
顶点顶点顶点输出innerVertexShader(顶点顶点在[[stage_in]]中){
垂直输出;
out.position=in.position;
返回;
};
fragment half4 innerFragmentShader(VertexOut in[[stage_in]],
半色调4颜色[[颜色(0)]){
半4输出;
output=color;//测试获取渲染颜色是否有效
output.g=in.position.y;//测试获取y是否有效
返回输出;
}
这些着色器在SCNTechnique字典中引用

[
“通行证”:[
“内部通行证:[
“绘制”:“绘制节点”,
“节点”:“内部”,
“metalVertexShader”:“innerVertexShader”,
“MetaFragmentShader”:“innerFragmentShader”
]
],
“序列”:[“内部过程”],
“符号”:[:],
“目标”:[:],
]
// ...
let technique=SCNTechnique(字典:techniqueDictionary)
这将执行以下操作:该技术被正确实例化并附加到场景(因为它会影响渲染)。但它似乎没有将摄影机变换或节点位置变换应用到顶点。而是将每个节点渲染为从(0,0,1)位置(0,0,0)处的(0,0,1)查看。颜色错误。如果我从SCNTE技术中删除着色器,每个渲染都会像我期望的那样

如何利用常规场景基特行为(摄影机变换等),仅根据片段的y世界位置修改颜色输出?我希望这需要在片段级别上发生,使用在顶点着色器中以某种方式获得的世界位置。我搜索了“金属基本顶点着色器”之类的内容“什么也没有想到。 我见过着色器,但我相信我应该能够依靠SceneKit渲染来处理照明、PBR材质、相机变换等。在这一点上,我觉得每当我搜索某个金属主题时,我都会出现在同一个网站上,这些网站还没有成功地将我的理解提升到一个新的水平。因此,任何新的/额外的资源也将受到赞赏

背景 在过去的两个月里,我一直在做我自己的游戏项目,它使用SceneKit作为主要的图形框架。我已经转向SCNTechnique和金属材质的自定义效果。特别是后两个问题让我头疼不已,都是因为缺少示例代码/文档/运行时反馈。
我已经考虑过转移到Unity/Unreal,甚至因为这个原因取消这个项目。但因为我很固执,也因为我真的不想把我的Swift代码移植到C#/C++,我还没有放弃SceneKit。

在过去几天研究这个话题之后,我对顶点和片段着色以及SceneKit如何处理这些事情的理解有了很大的发展

正如@mnuages在一篇评论中指出的那样,对于这个用例,着色器修改器是一个不错的选择。它们利用默认的SceneKit着色(根据OP的要求),并允许着色器代码注入

补充资料 为了弥补SceneKit文档的一些局限性,我将为其他研究该主题的人详细介绍一下

有关着色器修改器如何绑定到SceneKit默认顶点/片段着色器的详细信息,请参见或。第二个链接演示了使用着色器修改器而不是编写自己的着色器时免费获得的SceneKit渲染逻辑的范围

帮助我理解从顶点到片段(模型空间)的向量变换的不同阶段➡️ 世界空间➡️ 摄像机空间➡️ 投影空间)

替代方法(自定义着色器) 如果希望使用完全自定义的着色器进行单次传递,这是一个简单的示例。它将世界y位置从顶点着色器传递到片段着色器

//Xcode项目中的Shaders.metal文件
#包括
使用金属;
#包括
类型定义结构{
float4x4模型变换;
float4x4modelviewtransform;
}公共轮廓节点;
结构蛋白{
float3位置[[属性(SCNVertexSemanticPosition)];
};
结构顶点输出{
浮动4碎片位置[[位置]];
浮动高度;
};
顶点顶点输出myVertex(
维替克星[stage_in]],
恒定SCNSceneBuffer和scn_帧[[buffer(0)],
常量commonprofile_节点和scn_节点[[缓冲区(1)]]
) {
垂直输出;
float4位置=float4(in.position,1.f);
out.fragmentPosition=scn\u frame.viewProjectionTransform*scn\u node.modelTransform*位置;
//存储片段着色的世界位置
out.height=(scn_node.modelTransform*位置).y;
返回;
}
片段half4 myFragment(垂直外显子位于[[stage_in]]{
回位半部4(英寸高);
}
let字典:[字符串:任意]=[
“通行证”:[