带有 SceneKit SCNProgram 的金属着色器
Metal Shader with SceneKit SCNProgram
我正在寻找一个可以在 SceneKit 中使用 SCNProgram 工作的 Metal 着色器。
有人可以告诉我正确的方法 declarations/how 吗?
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
}
我只是在寻找最基本的例子。
我剪掉了所有 'unnecessary' 的东西,这是最基本的,几乎就是我的第一个金属着色器。
接下来我将开始研究连接其他顶点属性(颜色、法线),并可能进行一些基本的光照计算。
#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;
}
对任何打字错误表示歉意,在我的 phone...
上对其进行了编辑
@lock 上面的回答很好,所以我想通过提供一个纹理示例来扩展它,正如 OP 在评论中所要求的那样。
以下是配置 material 以使用着色器和连接自定义纹理的方法:
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);
}
我正在寻找一个可以在 SceneKit 中使用 SCNProgram 工作的 Metal 着色器。
有人可以告诉我正确的方法 declarations/how 吗?
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
}
我只是在寻找最基本的例子。
我剪掉了所有 'unnecessary' 的东西,这是最基本的,几乎就是我的第一个金属着色器。
接下来我将开始研究连接其他顶点属性(颜色、法线),并可能进行一些基本的光照计算。
#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;
}
对任何打字错误表示歉意,在我的 phone...
上对其进行了编辑@lock 上面的回答很好,所以我想通过提供一个纹理示例来扩展它,正如 OP 在评论中所要求的那样。
以下是配置 material 以使用着色器和连接自定义纹理的方法:
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);
}