Как применить импульсный эффект на объект SCNSphere?

Я хочу применить импульсный эффект к объекту SCNSphere, может ли кто-нибудь помочь мне в этом.

Импульсный эффект

введите описание изображения здесь

Заранее спасибо.

Я получил аналогичный эффект (см. Ниже) в одном из моих приложений и использовал модификатор шейдера SceneKit.

Импульсный эффект в SceneKit

Вот пример кода, который может помочь.

let boxNode = SCNNode(geometry: SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0)) boxNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red scene.rootNode.addChildNode(boxNode) let pulseSize:CGFloat = 5.0 let pulsePlane = SCNPlane(width: pulseSize, height: pulseSize) pulsePlane.firstMaterial?.isDoubleSided = true pulsePlane.firstMaterial?.diffuse.contents = UIColor.blue let pulseNode = SCNNode(geometry: pulsePlane) let pulseShaderModifier = "#pragma transparent; \n" + "vec4 originalColour = _surface.diffuse; \n" + "vec4 transformed_position = u_inverseModelTransform * u_inverseViewTransform * vec4(_surface.position, 1.0); \n" + "vec2 xy = vec2(transformed_position.x, transformed_position.y); \n" + "float xyLength = length(xy); \n" + "float xyLengthNormalised = xyLength/" + String(describing: pulseSize / 2) + "; \n" + "float speedFactor = 1.5; \n" + "float maxDist = fmod(u_time, speedFactor) / speedFactor; \n" + "float distbasedalpha = step(maxDist, xyLengthNormalised); \n" + "distbasedalpha = max(distbasedalpha, maxDist); \n" + "_surface.diffuse = mix(originalColour, vec4(0.0), distbasedalpha);" pulsePlane.firstMaterial?.shaderModifiers = [SCNShaderModifierEntryPoint.surface:pulseShaderModifier] boxNode.addChildNode(pulseNode) 

Красная рамка ( boxNode ) включена только для контекста.

Импульсный узел состоит из SCNPlane , для которого шейдер фрагмента модифицирован с помощью модификатора поверхностного шейдера SceneKit. Если вы закомментируете код, который устанавливает модификатор шейдера, вы увидите плоский синий квадрат, как ожидалось.

Код, указанный для точки входа поверхности шейдерного модификатора, вводится в шейдер фрагмента SceneKit. Это означает, что вы работаете в пространстве экрана с пикселями. Первые несколько строк модификатора шейдера переводят пространственные координаты экрана обратно в пространственные координаты модели, используя обратную модель и преобразования вида.

Каждое отображаемое расстояние пикселей до центра плоскости (в пространстве модели) вычисляется xyLength . Затем это нормализуется для общего размера «плоскости импульса» xyLengthNormalised . Для получения импульсного эффекта используется модульная операция вовремя; вы можете переключить это на функцию sin чтобы получить пульсирующий импульс in-then-out. Мы используем результат операции mod, чтобы определить, какие пиксели должны быть прозрачными.

Плоскость вращается с красным полем, поскольку это дочерний узел коробки. Вы можете переопределить это поведение, добавив ограничение, как показано ниже. Я использовал взгляд на ограничение, поскольку у меня никогда не было большого успеха с SCNBillboardConstraint .

 let pulseNodeConstraint = SCNLookAtConstraint(target: cameraNode) pulseNode.constraints = [pulseNodeConstraint] 

Конечный результат

Импульсный эффект в SceneKit с ограничением

Для тех, кто предпочитает Objective-C …

 SCNNode *boxNode = [SCNNode nodeWithGeometry:[SCNBox boxWithWidth:1.0 height:1.0 length:1.0 chamferRadius:0.0]]; boxNode.geometry.firstMaterial.diffuse.contents = [UIColor redColor]; [scene.rootNode addChildNode:boxNode]; CGFloat pulseSize = 5.0; SCNPlane *pulsePlane = [SCNPlane planeWithWidth:pulseSize height:pulseSize]; [pulsePlane.firstMaterial setDoubleSided:true]; pulsePlane.firstMaterial.diffuse.contents = [UIColor blueColor]; SCNNode *pulseNode = [SCNNode nodeWithGeometry:pulsePlane]; NSString *pulseShaderModifier = [NSString stringWithFormat: @"#pragma transparent; \n" "vec4 originalColour = _surface.diffuse; \n" "vec4 transformed_position = u_inverseModelTransform * u_inverseViewTransform * vec4(_surface.position, 1.0); \n" "vec2 xy = vec2(transformed_position.x, transformed_position.y); \n" "float xyLength = length(xy); \n" "float xyLengthNormalised = xyLength/%f; \n" "float speedFactor = 1.5; \n" "float maxDist = fmod(u_time, speedFactor) / speedFactor; \n" "float distbasedalpha = step(maxDist, xyLengthNormalised); \n" "distbasedalpha = max(distbasedalpha, maxDist); \n" "_surface.diffuse = mix(originalColour, vec4(0.0), distbasedalpha);", pulseSize/2.0]; NSDictionary *smdict = [NSDictionary dictionaryWithObject:pulseShaderModifier forKey:SCNShaderModifierEntryPointSurface]; [pulsePlane.firstMaterial setShaderModifiers:smdict]; [boxNode addChildNode:pulseNode]; SCNLookAtConstraint *pulseNodeConstraint = [SCNLookAtConstraint lookAtConstraintWithTarget:cameraNode]; NSArray *constraints = [NSArray arrayWithObject:pulseNodeConstraint]; [pulseNode setConstraints:constraints]; 

Вы можете использовать pod из https://github.com/shu223/Pulsator

конфигурировать

 let pulsator = Pulsator() view.layer.addSublayer(pulsator) pulsator.start() 

Количество импульсов

 pulsator.numPulse = 3 

Радиус

 pulsator.radius = 240.0 

цвет

 pulsator.backgroundColor = UIColor(red: 1, green: 1, blue: 0, alpha: 1).CGColor 

Продолжительность анимации

Используйте следующие свойства

 animationDuration : duration for each pulse pulseInterval : interval between pulses 

смягчение

Вы можете установить свойство timingFunction .

Повторение

Используйте свойство repeatCount .

Просто настроил его правильно. Удачи.