首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于顶点世界位置Y坐标修改金属碎片着色

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

Stack Overflow用户
提问于 2020-04-12 21:06:38
回答 1查看 527关注 0票数 2

我正在尝试使用带有SCNTechnique的金属碎片着色器来修改基于顶点Y世界位置的碎片颜色。

我到目前为止的理解

可以使用一系列渲染过程配置SCNTechnique。渲染过程允许注入顶点和片段着色器。这些着色器是用Metal编写的。Metal Shading Language Specification描述了这两者所支持的输入/输出。将为要渲染的每个顶点调用顶点着色器。我们可以将其他信息从顶点着色器传递到片段着色器(如3D空间中的位置,请参见MSLS section 5.2)。片段着色器最接近像素,如果有多个三角形“符合”该像素,则可能称为单个“像素”的多次着色器。(通常)在片断着色之后,如果片断未通过深度或模具测试,则可能会丢弃片断。

我所尝试的

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

代码语言:javascript
复制
struct VertexOut {
    float4 position [[position]];
};

vertex VertexOut innerVertexShader(VertexIn in [[stage_in]]) {
    VertexOut out;
    out.position = in.position;
    return out;
};

fragment half4 innerFragmentShader(VertexOut in [[stage_in]],
                                   half4 color [[color(0)]]) {
    half4 output;
    output = color;           // test to see if getting rendered color works
    output.g = in.position.y; // test to see if getting y works
    return output;
}

这些着色器在SCNTechnique字典中引用。

代码语言:javascript
复制
[
    "passes": [
        "innerPass: [
            "draw": "DRAW_NODE",
            "node": "inner",
            "metalVertexShader": "innerVertexShader",
            "metalFragmentShader": "innerFragmentShader"
        ]
    ],
    "sequence": ["innerPass"],
    "symbols": [:],
    "targets": [:],
]

// ...

let technique = SCNTechnique(dictionary: techniqueDictionary)

这将执行以下操作:正确实例化该技术并将其附加到场景(因为它会影响渲染)。但它似乎不会将摄影机变换或节点位置变换应用于顶点。并且取而代之地将每个节点呈现为从位置(0,0,0)处的(0,0,1)观看。颜色不对。如果我从SCNTechnique中移除着色器,所有渲染都会像我预期的那样渲染。

如何利用常规的SceneKit行为(相机变换等),并且仅根据碎片的世界位置修改颜色输出?我预计这需要在片段级别上发生,使用在顶点着色器中以某种方式获得的世界位置。我已经搜索了像"Metal basic vertex shader“这样的东西,但什么也没有找到。我已经看到了着色器like this,但我相信我应该能够依靠SceneKit渲染的东西,如照明,PBR材质,相机变换,等等。在这一点上,我觉得每当我搜索一些金属主题,我结束了相同的网站,但尚未成功地将我的理解提升到一个新的水平。因此,任何新的/额外的资源也是值得感谢的。

背景

在过去的两个月里,我一直在做我自己的游戏项目,它使用SceneKit作为主要的图形框架。我已经转向SCNTechnique和金属着色器来实现自定义效果。后两个尤其让我头疼,都是因为缺乏示例代码/文档/运行时反馈。由于这个原因,我已经考虑转移到Unity/虚幻,甚至完全取消这个项目。但因为我很固执,也因为我真的不想把我的Swift代码移植到C#/C++,所以我还没有放弃SceneKit。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-15 23:31:15

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

正如@mnuages在评论中指出的那样,对于这种用例,着色器修饰符是可行的。它们利用默认的SceneKit着色(根据OP的要求),并允许着色器代码注入。

更多信息

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

有关着色器修改器如何绑定到SceneKit默认顶点/片段着色器的详细信息,请参见my answer to a related questionSceneKit's default shaders。第二个链接演示了SceneKit的渲染逻辑的范围,当利用着色器修改器而不是编写自己的着色器时,您可以免费获得这些逻辑。

This page帮助我理解了从顶点到片段的向量转换的不同阶段(模型空间、➡️世界空间、➡️相机空间、➡️投影空间)。

备用方法(自定义着色器)

如果您希望使用完全自定义的着色器进行单过程,则这是一个简单的示例。它将世界y位置从顶点着色器传递到片段着色器。

代码语言:javascript
复制
// Shaders.metal file in your Xcode project

#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>

typedef struct {
    float4x4 modelTransform;
    float4x4 modelViewTransform;
} commonprofile_node;

struct VertexIn {
    float3 position [[attribute(SCNVertexSemanticPosition)]];
};

struct VertexOut {
    float4 fragmentPosition [[position]];
    float height;
};

vertex VertexOut myVertex(
                          VertexIn in [[stage_in]],
                          constant SCNSceneBuffer& scn_frame [[buffer(0)]],
                          constant commonprofile_node& scn_node [[buffer(1)]]
                          ) {
    VertexOut out;

    float4 position = float4(in.position, 1.f);
    out.fragmentPosition = scn_frame.viewProjectionTransform * scn_node.modelTransform * position;

    // store world position for fragment shading
    out.height = (scn_node.modelTransform * position).y;
    return out;
}

fragment half4 myFragment(VertexOut in [[stage_in]]) {
    return half4(in.height);
}
代码语言:javascript
复制
let dictionary: [String: Any] = [
    "passes" : [
        "y" : [
            "draw" : "DRAW_SCENE",
            "inputs" : [:],
            "outputs" : [
                "color" : "COLOR"
            ],
            "metalVertexShader": "myVertex",
            "metalFragmentShader": "myFragment",
        ]
    ],
    "sequence" : ["y"],
    "symbols" : [:]
]

let technique = SCNTechnique(dictionary: dictionary)
scnView.technique = technique

可以将该渲染过程与其他过程结合使用(请参见SCNTechnique)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61171947

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档