Jak napisać modyfikator sceneKit shader dla efektu
Chciałbym zbudować grę Scenekit. Przyglądałem się modyfikatorom shader, ponieważ wydają się być najlżejsze i nie miałem szczęścia w replikowaniu tego efektu: {]}
Czy można użyć modyfikatorów shader do stworzenia tego efektu? Jak byś to zrobił?
1 answers
Możesz zbliżyć się do zamierzonego efektu za pomocą modyfikatora shadera fragmentów. Podstawowe podejście jest następujące:
- próbka z tekstury szumu
- jeśli próbka szumu jest poniżej pewnego progu (który nazywam "ujawnieniem"), odrzuć ją, czyniąc ją całkowicie przezroczystą
- W przeciwnym razie, jeśli fragment znajduje się blisko krawędzi, zastąp jego kolor preferowanym kolorem krawędzi (lub gradientem)
- Zastosuj bloom, aby krawędzie świeciły
Oto kod modyfikatora shadera do tego celu:
#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;
}
Zwróć uwagę, że parametr revealage jest wyświetlany jako parametr materialny, ponieważ możesz chcieć go animować. Istnieją inne stałe wewnętrzne, takie jak szerokość krawędzi i skala szumów, które można dopracować, aby uzyskać pożądany efekt z zawartością.
Różne tekstury szumów dają różne efekty rozpuszczania, więc możesz z tym eksperymentować. Właśnie użyłem tego szumu wartości multioktave image:
Załaduj obraz jako UIImage
lub NSImage
i ustaw go na właściwości materiału, który zostanie odsłonięty jako noiseTexture
:
material.setValue(SCNMaterialProperty(contents: noiseImage), forKey: "noiseTexture")
Musisz dodać bloom jako post-proces, aby uzyskać ten błyszczący, e-wire efekt. W SceneKit jest to tak proste, jak włączenie potoku HDR i ustawienie niektórych parametrów:
let camera = SCNCamera()
camera.wantsHDR = true
camera.bloomThreshold = 0.8
camera.bloomIntensity = 2
camera.bloomBlurRadius = 16.0
camera.wantsExposureAdaptation = false
Wszystkie parametry numeryczne będą musiały być dopasowane do Twojej zawartości.
Aby wszystko było uporządkowane, wolę zachować shader modyfikatory w ich własnych plikach tekstowych (ja nazwałem swój " dissolve.fragment.txt"). Oto jak załadować kod modyfikujący i dołączyć go do materiału.
let modifierURL = Bundle.main.url(forResource: "dissolve.fragment", withExtension: "txt")!
let modifierString = try! String(contentsOf: modifierURL)
material.shaderModifiers = [
SCNShaderModifierEntryPoint.fragment : modifierString
]
I na koniec, aby ożywić efekt, możesz użyć CABasicAnimation
owiniętego 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")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-07 09:32:03