使用``clip_distance``的SceneKit Metal着色器

问题描述

我正在修改https://medium.com/@MalikAlayli/metal-with-scenekit-create-your-first-shader-2c4e4e983300中提供的SceneKit Metal着色器。它将显示具有图像纹理的多维数据集,该场景由SceneKit与金属着色器渲染。

我使用SCNSphere(radius: 3)将立方体更改为以(0,0)为中心的半径3的球体。然后,我使用clip_distance来“切掉”满足in.position.z > 1.5的球体的一部分。结果如下图所示。我正在使用的Metal着色器也在下面给出。

如您所见,边界不平滑。它显示多边形的边界,而不是插值曲面。那么,是否有可能使它平滑?如果是,怎么办?谢谢。

enter image description here

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

解决方法

剪切距离将在图元上进行线性插值,并且插值距离小于0.0的图元部分将被剪切。 (gl_ClipDistance

要使裁剪后的片段的边界恰好位于z = 1.5,请确保插入的裁剪距离在0.0时恰好位于z = 1.5,然后在每一侧都为正或负。

out.clip_distance = (1.5 - in.position.z);