2016-06-08 79 views
4

我正在尋找一個可以在SceneKit中使用SCNProgram工作的金屬着色器。金屬着色器與SceneKit SCNProgram

有人可以告訴我正確的方法聲明/如何掛鉤嗎?

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

,然後着色器

//MyShader.metal 

vertex something myVertex(something) 
{ 
    return something; 
} 

fragment float4 myFragment(something) 
{ 
    return something 
} 

我只是在尋找最簡單的例子吧。

回答

6

我剪掉了所有'不必要'的東西,這與我的第一個金屬着色器的基本相同。

接下來,我會着手尋找其他頂點屬性(顏色,法線)的連線,並且可能會進行一些基本的照明計算。

#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; 
} 

道歉任何錯別字,編輯下來我的電話......

+0

這真的很棒,你有沒有通過SCNNode材質設置的紋理的例子? - 現在可以理解,它只是將我的物體塗成紅色。 – Chris

3

@以上鎖的答案是偉大的,所以我想通過提供紋理的一個例子就可以擴大,如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") 

,這裏是修改後的着色器從紋理樣本:

#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); 
} 
+0

謝謝謝謝謝謝!我會完全給你提供這個。我已經帶來了你的書沃倫,這正是我需要的! – Chris

+0

哈哈,很高興幫助。並感謝您支持這本書:) – warrenm

+0

這個設置可以用於某種多着色器設置,其中第一個着色器創建第二個着色器使用的紋理,第二個着色器是呈現的紋理器? – Chris