在我的SceneKit node 上,我希望应用磨砂玻璃效果,如下所示:

https://www.shadertoy.com/view/WdSGz1

该着色器将纹理作为输入,并输出纹理的"模糊"版本.我想要的是创建一个SCNProgram(),并将其应用于我的一个 node 的material ,以便它具有磨砂玻璃纹理.

我试着用金属着色器重现这一点,但我不太熟悉它的工作原理.我是这样写的:

#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>

struct NodeBuffer {
    float4x4 modelTransform;
    float4x4 modelViewProjectionTransform;
    float4x4 modelViewTransform;
    float4x4 normalTransform;
    float2x3 boundingBox;
};

struct MyNodeBuffer {
    float4x4 modelTransform;
    float4x4 inverseModelTransform;
    float4x4 modelViewTransform;
    float4x4 inverseModelViewTransform;
    float4x4 normalTransform;
    float4x4 modelViewProjectionTransform;
    float4x4 inverseModelViewProjectionTransform;
};

struct VertexInput {
    float3 position  [[attribute(SCNVertexSemanticPosition)]];
    float2 uv [[attribute(SCNVertexSemanticTexcoord0)]];
};

struct VertexOut {
    float4 position [[position]];
    float2 uv;
};

vertex VertexOut vertexFunction(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;
    return out;
};

float stepfun(float x) {
    return (sign(x) + 1.0) / 2.0;
}

float square(float2 pos) {
    return (stepfun(pos.x + 1.0) * stepfun(1.0 - pos.x)) *
        (stepfun(pos.y + 1.0) * stepfun(1.0 - pos.y));
};

constexpr sampler textureSampler(coord::normalized, filter::linear, address::repeat);

float2 dist(float2 pos, texture2d<float,access::sample> texture [[ texture(0) ]])
{
    float2 offset = pos;
    return pos + square((offset - 0.5) * 3.0) * texture.sample(textureSampler, (offset - 0.5) * 5.0).xy * 0.05;
}

fragment float4 fragmentFunction(VertexOut out [[ stage_in ]],
                            texture2d<float, access::sample> texture [[ texture(0) ]],
                            device float3 *resolution [[ buffer(0) ]])
{
    float2 uv = out.uv / resolution[0].xy;
    float4 tex = texture.sample(textureSampler, dist(uv, texture));
    tex.a = 0.5;
    return tex;
}

但是,我需要将纹理作为我的FragmentFunction的输入,而我不知道这应该是什么.我希望它是我的 node 在没有着色器的情况下的纹理.

推荐答案

嗯,我可能也找到了类似的东西.

try 使用法线贴图,这类似于一些霜冻效果.

func foregroundObjectFrostNormal() {
    
    let plane = SCNPlane(width: 3.0, height: 3.0) // SCNSphere(radius: 1.5)
    
    plane.firstMaterial?.diffuse.contents   = UIColor.lightGray
    plane.firstMaterial?.normal.contents    = UIImage.init(named: "art.scnassets/frost_normal/frost_long.png")
    plane.firstMaterial?.roughness.contents = 0.1
    plane.firstMaterial?.metalness.contents = 0.0
    plane.firstMaterial?.transparency = 0.25
    plane.firstMaterial?.lightingModel = .physicallyBased
    
    let node = SCNNode(geometry: plane)
    node.position = SCNVector3(0.0, 0.0, +3.0)
    scene.rootNode.addChildNode(node)
    
}

simulated frost

这是一个项目,你可以看到效果,并try : https://drive.google.com/file/d/1mCZ2OrxkCENO6TMeQe5HctyAdpgz5gv8/view?usp=share_link

Swift相关问答推荐

AirPods手势不发送AVAudioApp静音状态通知

map 视图上的SwiftUI渐变折线

如何在visionOS中定制悬停效果区域

我在SwiftUI中的动画无法正常工作

如何强制创建新的UIViewControllerRenatable|更新Make UIViewController上的视图

如何在SwiftUI的文本视图中显示NSMutableAttributedString?

减小SF符号的边框宽度

为什么自定义串行队列的目标是全局队列时,Swift中不会并发执行?

为什么无法在 Swift 中使用AVFoundation扫描 QRCode

仅当 boolean 为真时才实现方法(application:didReceiveRemoteNotification)

无法使用 RealityKit 播放 USDZ 动画

在 macOS (Swift) 上获取 BSD 驱动器名称的最佳方法是什么?

为什么 Apple Scrumdinger Sample App 使用两个事实来源?

使用 Swiftui 水平修剪 Shape()

Swift - 导入我的 swift 类

UITableViewCell 不显示 detailTextLabel.text - Swift

Swift 中的 CommonHMAC

更改在变量的 willSet 块中设置的值

swift 中的@property/@synthesize 类似功能

判断用户是否登录到 iCloud?Swift /iOS