使用 ``clip_distance`` 的 SceneKit Metal 着色器
SceneKit Metal shader using ``clip_distance``
我正在修改 https://medium.com/@MalikAlayli/metal-with-scenekit-create-your-first-shader-2c4e4e983300 中给出的 SceneKit Metal 着色器。它显示一个带有图像纹理的立方体,由 SceneKit 使用金属着色器渲染。
我使用 SCNSphere(radius: 3)
将立方体更改为半径为 3、以 (0,0,0) 为中心的球体。然后,我用clip_distance
把满足in.position.z > 1.5
的球体“切”掉了一部分。结果如下图所示。下面也给出了我使用的Metal shader。
如你所见,边界并不平滑。它显示多边形的边界,而不是插值表面。那么,有没有可能让它变得平滑呢?如果是,如何?谢谢。
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct NodeBuffer {
float4x4 modelTransform;
float4x4 modelViewProjectionTransform;
float4x4 modelViewTransform;
float4x4 normalTransform;
float2x3 boundingBox;
};
struct VertexInput {
float3 position [[attribute(SCNVertexSemanticPosition)]];
float2 uv [[attribute(SCNVertexSemanticTexcoord0)]];
};
struct VertexOut {
float4 position [[position]];
float2 uv;
float clip_distance [[clip_distance]];
};
vertex VertexOut textureSamplerVertex(VertexInput in [[ stage_in ]], constant NodeBuffer& scn_node [[buffer(1)]]) {
VertexOut out;
out.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
out.uv = in.uv;
if ((in.position.z > 1.5)) {
out.clip_distance = -1;
}
else {
out.clip_distance = 1;
}
return out;
}
fragment float4 textureSamplerFragment(VertexOut out [[ stage_in ]], texture2d<float, access::sample> customTexture [[texture(0)]]) {
constexpr sampler textureSampler(coord::normalized, filter::linear, address::repeat);
return customTexture.sample(textureSampler, out.uv );
}
The clip distances will be linearly interpolated across the primitive and the portion of the primitive with interpolated distances less than 0.0 will be clipped. (gl_ClipDistance)
为了使剪辑片段的边界恰好位于 z = 1.5
,您需要确保当 z = 1.5
时插值剪辑距离恰好位于 0.0
,然后在每个片段上为正或负边.
out.clip_distance = (1.5 - in.position.z);
我正在修改 https://medium.com/@MalikAlayli/metal-with-scenekit-create-your-first-shader-2c4e4e983300 中给出的 SceneKit Metal 着色器。它显示一个带有图像纹理的立方体,由 SceneKit 使用金属着色器渲染。
我使用 SCNSphere(radius: 3)
将立方体更改为半径为 3、以 (0,0,0) 为中心的球体。然后,我用clip_distance
把满足in.position.z > 1.5
的球体“切”掉了一部分。结果如下图所示。下面也给出了我使用的Metal shader。
如你所见,边界并不平滑。它显示多边形的边界,而不是插值表面。那么,有没有可能让它变得平滑呢?如果是,如何?谢谢。
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct NodeBuffer {
float4x4 modelTransform;
float4x4 modelViewProjectionTransform;
float4x4 modelViewTransform;
float4x4 normalTransform;
float2x3 boundingBox;
};
struct VertexInput {
float3 position [[attribute(SCNVertexSemanticPosition)]];
float2 uv [[attribute(SCNVertexSemanticTexcoord0)]];
};
struct VertexOut {
float4 position [[position]];
float2 uv;
float clip_distance [[clip_distance]];
};
vertex VertexOut textureSamplerVertex(VertexInput in [[ stage_in ]], constant NodeBuffer& scn_node [[buffer(1)]]) {
VertexOut out;
out.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
out.uv = in.uv;
if ((in.position.z > 1.5)) {
out.clip_distance = -1;
}
else {
out.clip_distance = 1;
}
return out;
}
fragment float4 textureSamplerFragment(VertexOut out [[ stage_in ]], texture2d<float, access::sample> customTexture [[texture(0)]]) {
constexpr sampler textureSampler(coord::normalized, filter::linear, address::repeat);
return customTexture.sample(textureSampler, out.uv );
}
The clip distances will be linearly interpolated across the primitive and the portion of the primitive with interpolated distances less than 0.0 will be clipped. (gl_ClipDistance)
为了使剪辑片段的边界恰好位于 z = 1.5
,您需要确保当 z = 1.5
时插值剪辑距离恰好位于 0.0
,然后在每个片段上为正或负边.
out.clip_distance = (1.5 - in.position.z);