2016-06-08 66 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

相关问题