SceneKit: диффузная Альфа против прозрачности / прозрачный

Я пытаюсь достичь прозрачности для сетки в SceneKit на iOS. Я смущен документацией, поскольку существует несколько способов сделать сетку прозрачной:

  • используйте альфа-канал UIColor через SCNMaterial.(diffuse|emission|ambient|...).contents
  • использовать SCNMaterial.transparency (CGFloat от 0.0 до 1.0)
  • использовать SCNMaterial.transparent (другой SCNMaterialProperty)
  • использовать SCNNode.opacity (CGFloat от 0.0 (полностью прозрачный) до 1.0 (полностью опаковый))

вопросы:

  • есть ли подробное описание цветовой математики где-нибудь?
  • каков общий способ добавить прозрачность (на объект, а не через текстуры/на вершину)?
  • как SCNMaterial.transparent взаимодействие с другими цветовыми каналами, такими как diffuse?
  • правда ли, что альфа-канал должен быть предварительно умножен, как предложено в https://stackoverflow.com/a/30195543/278842?

1 ответов


некоторые свойства являются анимируемыми, некоторые из них применяют значение равномерно ко всему объекту, в то время как другие позволяют использовать текстуру Альфа-канала для управления прозрачностью для каждой точки. Применение значения к узлу с дочерними элементами позволяет задать значение прозрачности для нескольких узлов одновременно.

диффузная альфа-канал

вместо использования сетки с большим количеством вершин иногда можно использовать простые сетки с диффузными текстурами, см. также пример ниже.

SCNMaterial.прозрачность

отрегулируйте непрозрачность равномерно для всего материала. Это свойство является анимируемым.

SCNMaterial.прозрачный

вместо того, чтобы устанавливать значение прозрачности для всего материала, вы можете установить непрозрачность для каждой точки отдельно, обычно используя текстуру.

SCNNode.непрозрачность

устанавливает непрозрачность целого узла и детей.

существует еще больше контроля возможно:

SCNMaterial.transparencyMode

С свойством transparencyMode материала вы можете использовать различные режимы: .aOne использует альфа-канал,.rgbzero определяет прозрачность от яркости цвета.

Цвет Math

цветовая математика определяется режимом наложения и описывается здесь:

https://developer.apple.com/documentation/scenekit/scnblendmode

случае альфа

Blend путем умножения цвета источника и назначения значения по их соответствующим Альфа-значениям.

case add

смешайте, добавив исходный цвет к целевому цвету.

случае вычесть

Blend by вычитание цвета источника из цвета назначения.

случае умножьте

смешать путем умножения исходного цвета на цвет фона.

случае экрана

Blend путем умножения инверсии исходного цвета на инверсию цвета назначения.

случае заменить

Blend путем замены цвета назначения на цвет источника, игнорируя Альфу.

примеры

Деревья / Листва

вместо использования сеток с большим количеством вершин, что привело бы к заметному или даже неприемлемому снижению частоты кадров, часто можно использовать прозрачные диффузные текстуры. Хорошим примером для этого являются, например, деревья и листья.

здесь вы видите слева прозрачную текстуру, в середине сетка с несколькими простыми плоскостями и на правильно, как это выглядит при визуализации SceneKit (сетка и текстура взяты изhttp://www.loopix-project.com).

leaves

let mat = SCNMaterial()
mat.diffuse.contents = "palms1.png"
if let geometry = palm.geometry {
    geometry.materials = [mat]
}

зарево эффект

для различных эффектов можно использовать режим наложения, например, для получения эффекта свечения можно использовать blendMode .добавить:

mat.blendMode = .add

Fade in/Fade out

SCNNode.непрозрачность относится к узлу, включающему все подузлы. Это свойство является анимируемым, поэтому, если вы хотите исчезнуть в или из узла (или группы узлов), это правильный путь.

вы также используете это для применения прозрачности для каждого объекта.

предварительно умноженная Альфа против прямой Альфа

внутренне SceneKit использует предварительно умноженную Альфа. Поэтому, если вы пишете шейдеры, вы должны знать об этом.

если вы работаете только на уровне API, вы не затронуты, например, если вы загружаете a.png файл с прозрачность, вам не нужно ничего делать, чтобы предварительно умножить RGB самостоятельно.

взаимодействие, например, SCNMaterial.прозрачный с другими каналами

прозрачные пленки должны использоваться вместе для различных сценариев использования. Например, вы хотите удалить объект с уже частично прозрачными областями.

искусственный демонстрационный пример

  • сфера с текстурой шума, что уже прозрачные области

  • покажите сферу с материальной Альфой .75

  • добавить вторую сферу для сравнения

настройки:

let sphere1 = SCNSphere(radius: 0.5)
let material1 = SCNMaterial()
material1.diffuse.contents = "art.scnassets/colorTex.png"
material1.transparent.contents = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
sphere1.materials = [material1]
let sphereNode1 = SCNNode(geometry: sphere1)
sphereNode1.position = SCNVector3(x: 0, y: -2, z: 0)

let sphere2 = SCNSphere(radius: 0.25)
let sphereNode2 = SCNNode(geometry: sphere2)
sphereNode2.position = SCNVector3(x: 0, y: -0.5, z: 0)

let spheres = SCNNode()
spheres.addChildNode(sphereNode1)
spheres.addChildNode(sphereNode2)
self.scnScene.rootNode.addChildNode(spheres)

теперь примените fade out через SCNNode.непрозрачность:

let fadeOut = SCNAction.customAction(duration: 5) { (node, elapsedTime) -> () in
    node.opacity = 1 - elapsedTime / 5
}

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    spheres.runAction(fadeOut)
}

результат выглядит так:

combined transparency