如何写在效果溶解sceneKit着色器修改

问题描述 投票:5回答:1

我想建立一个Scenekit游戏效果的溶解。我一直在寻找到着色修饰,因为他们似乎是最重量轻,在复制这样的效果还没有得到任何运气:

Dissolve shader effect

是否有可能使用着色器修饰符来产生这种效果?你会如何去实现呢?

ios swift shader scenekit metal
1个回答
16
投票

你可以得到相当接近与片段着色器修改了预期的效果。其基本做法是:

  • 从噪声纹理采样
  • 如果噪声样本是低于一定的阈值(其我称之为“revealage”),丢弃它,使它完全透明
  • 否则,如果所述片段是靠近边缘,与边缘优选颜色(或梯度)替换它的颜色
  • 应用绽放,使边缘发光

下面是这样做的着色器修改代码:

#pragma arguments

float revealage;
texture2d<float, access::sample> noiseTexture;

#pragma transparent
#pragma body

const float edgeWidth = 0.02;
const float edgeBrightness = 2;
const float3 innerColor = float3(0.4, 0.8, 1);
const float3 outerColor = float3(0, 0.5, 1);
const float noiseScale = 3;

constexpr sampler noiseSampler(filter::linear, address::repeat);
float2 noiseCoords = noiseScale * _surface.ambientTexcoord;
float noiseValue = noiseTexture.sample(noiseSampler, noiseCoords).r;

if (noiseValue > revealage) {
    discard_fragment();
}

float edgeDist = revealage - noiseValue;
if (edgeDist < edgeWidth) {
    float t = edgeDist / edgeWidth;
    float3 edgeColor = edgeBrightness * mix(outerColor, innerColor, t);
    _output.color.rgb = edgeColor;
}

请注意,revealage参数公开为材料参数,因为你可能想制作动画。有其它的内部常数,如边缘宽度和噪声比例可微调以获得与内容所期望的效果。

不同的噪声纹理产生不同的效果溶解,这样你就可以与实验以及。我只是用这个multioctave值噪声图像:

Value noise image used as dissolve texture

加载图像作为UIImageNSImage,并将其设置在该被暴露为noiseTexture材料性质:

material.setValue(SCNMaterialProperty(contents: noiseImage), forKey: "noiseTexture")

你需要添加绽放的后处理得到那个发光效果,电子线效果。在SceneKit,这是为使HDR管道并设置一些参数一样简单:

let camera = SCNCamera()
camera.wantsHDR = true
camera.bloomThreshold = 0.8
camera.bloomIntensity = 2
camera.bloomBlurRadius = 16.0
camera.wantsExposureAdaptation = false

所有的数字参数将有可能需要调整您的内容。

为了保持整洁,我喜欢保持着色修饰自己的文本文件(我将其命名“dissolve.fragment.txt”)。以下是如何加载一些修改代码,并将其连接到的材料。

let modifierURL = Bundle.main.url(forResource: "dissolve.fragment", withExtension: "txt")!
let modifierString = try! String(contentsOf: modifierURL)
material.shaderModifiers = [
    SCNShaderModifierEntryPoint.fragment : modifierString
]

最后,动画效果,你可以使用包裹着CABasicAnimation一个SCNAnimation

let revealAnimation = CABasicAnimation(keyPath: "revealage")
revealAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
revealAnimation.duration = 2.5
revealAnimation.fromValue = 0.0
revealAnimation.toValue = 1.0
let scnRevealAnimation = SCNAnimation(caAnimation: revealAnimation)
material.addAnimation(scnRevealAnimation, forKey: "Reveal")

© www.soinside.com 2019 - 2024. All rights reserved.