带SceneKit SCNProgram的金属着色器

Chr*_*ris 7 shader scenekit metal

我正在寻找一个可以在SceneKit中使用SCNProgram工作的金属着色器.

有人能告诉我正确的方法声明/如何挂钩吗?

let program = SCNProgram()
program.vertexFunctionName = "myVertex"
program.fragmentFunctionName = "myFragment"
material.program = program
Run Code Online (Sandbox Code Playgroud)

然后是着色器

//MyShader.metal

vertex something myVertex(something)
{
    return something;
}

fragment float4 myFragment(something)
{
    return something
}
Run Code Online (Sandbox Code Playgroud)

我只想找到最基本的例子.

loc*_*ock 11

我剪掉了所有'不必要的'东西,这是基本的,它几乎是我的第一个金属着色器.

接下来,我将开始研究其他顶点属性(颜色,法线)的连线,并可能进行一些基本的光照计算.

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

struct MyNodeBuffer {
    float4x4 modelTransform;
    float4x4 modelViewTransform;
    float4x4 normalTransform;
    float4x4 modelViewProjectionTransform;
};

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

struct SimpleVertex
{
    float4 position [[position]];
};


vertex SimpleVertex myVertex(MyVertexInput in [[ stage_in ]],
                             constant SCNSceneBuffer& scn_frame [[buffer(0)]],
                             constant MyNodeBuffer& scn_node [[buffer(1)]])
{
    SimpleVertex vert;
    vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);

    return vert;
}

fragment half4 myFragment(SimpleVertex in [[stage_in]])
{
    half4 color;
    color = half4(1.0 ,0.0 ,0.0, 1.0);

    return color;
}
Run Code Online (Sandbox Code Playgroud)

为任何错别字道歉,在我的手机上编辑它...


war*_*enm 8

@lock的答案很好,所以我想通过提供一个纹理的例子来扩展它,就像评论中要求的OP一样.

以下是如何配置材质以使用着色器并连接自定义纹理:

let program = SCNProgram()
program.fragmentFunctionName = "myFragment"
program.vertexFunctionName = "myVertex"

material.program = program

let image = UIImage(named: "diffuse")!
let imageProperty = SCNMaterialProperty(contents: image)
// The name you supply here should match the texture parameter name in the fragment shader
material.setValue(imageProperty, forKey: "diffuseTexture")
Run Code Online (Sandbox Code Playgroud)

以下是从纹理中采样的修改后的着色器:

#include <metal_stdlib>

using namespace metal;

#include <SceneKit/scn_metal>

struct MyNodeBuffer {
    float4x4 modelTransform;
    float4x4 modelViewTransform;
    float4x4 normalTransform;
    float4x4 modelViewProjectionTransform;
};

typedef struct {
    float3 position [[ attribute(SCNVertexSemanticPosition) ]];
    float2 texCoords [[ attribute(SCNVertexSemanticTexcoord0) ]];
} MyVertexInput;

struct SimpleVertex
{
    float4 position [[position]];
    float2 texCoords;
};

vertex SimpleVertex myVertex(MyVertexInput in [[ stage_in ]],
                             constant SCNSceneBuffer& scn_frame [[buffer(0)]],
                             constant MyNodeBuffer& scn_node [[buffer(1)]])
{
    SimpleVertex vert;
    vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
    vert.texCoords = in.texCoords;

    return vert;
}

fragment half4 myFragment(SimpleVertex in [[stage_in]],
                          texture2d<float, access::sample> diffuseTexture [[texture(0)]])
{
    constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
    float4 color = diffuseTexture.sample(sampler2d, in.texCoords);
    return half4(color);
}
Run Code Online (Sandbox Code Playgroud)

  • 尽管理论上看起来很漂亮,但我得到的只是一个没有阴影或纹理的纯白色轮廓。知道我做错了什么吗?也许最近的 iOS 版本发生了一些变化? (2认同)