Metal Shader with SceneKit SCNProgram

后端 未结 2 644
梦谈多话
梦谈多话 2020-12-28 10:39

I\'m looking for just a working Metal shader that works in SceneKit with SCNProgram.

Can someone show me the correct method declarations/how to hook this up?

2条回答
  •  情歌与酒
    2020-12-28 10:47

    @lock's answer above is great, so I wanted to expand on it by providing an example of texturing, as OP requested in the comments.

    Here's how you'd configure your material to make use of the shaders and wire up the custom texture:

    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")
    

    and here are the modified shaders that sample from the texture:

    #include 
    
    using namespace metal;
    
    #include 
    
    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 diffuseTexture [[texture(0)]])
    {
        constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
        float4 color = diffuseTexture.sample(sampler2d, in.texCoords);
        return half4(color);
    }
    

提交回复
热议问题