View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Resumo
  • Código
  • Novidades na renderização no Metal para apps imersivos

    Descubra as melhorias mais recentes na renderização no Metal para apps imersivos com o framework Compositor Services. Saiba como adicionar efeitos de hover para destacar os elementos interativos do seu app e como renderizar com mais fidelidade usando qualidade de renderização dinâmica. Saiba mais sobre o novo estilo de imersão progressiva. Além disso, descubra como incluir experiências imersivas nos apps para macOS renderizando o conteúdo diretamente no Metal do Mac para o Vision Pro.

    Para aproveitar ao máximo esta sessão, primeiro assista ao vídeo “Discover Metal for immersive apps” da WWDC23.

    Capítulos

    • 0:00 - Introdução
    • 1:58 - Novas APIs de loops de renderização
    • 4:21 - Efeitos de foco
    • 10:50 - Qualidade de renderização dinâmica
    • 14:44 - Imersão progressiva
    • 18:32 - Renderização espacial para macOS
    • 23:51 - Próximas etapas

    Recursos

    • Analyzing the performance of your Metal app
    • Rendering hover effects in Metal immersive apps
    • Optimizing GPU performance
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC25

    • Aprimore jogos com o Metal 4
    • Conheça o Metal 4
    • Explore a entrada de acessórios espaciais no visionOS
    • Explore jogos feitos com o Metal 4
    • Novidades do SwiftUI
    • Novidades do visionOS 26

    WWDC24

    • Render Metal with passthrough in visionOS

    WWDC23

    • Discover Metal for immersive apps
  • Buscar neste vídeo...
    • 0:01 - Scene render loop

      // Scene render loop
      
      extension Renderer {
          func renderFrame(with scene: MyScene) {
              guard let frame = layerRenderer.queryNextFrame() else { return }
      
              frame.startUpdate()
              scene.performFrameIndependentUpdates()
              frame.endUpdate()
      
              let drawables = frame.queryDrawables()
              guard !drawables.isEmpty else { return }
      
              guard let timing = frame.predictTiming() else { return }
              LayerRenderer.Clock().wait(until: timing.optimalInputTime)
              frame.startSubmission()
              scene.render(to: drawable)
              frame.endSubmission()
          }
      }
    • 5:54 - Layer configuration

      // Layer configuration
      
      struct MyConfiguration: CompositorLayerConfiguration {
          func makeConfiguration(capabilities: LayerRenderer.Capabilities,
                                 configuration: inout LayerRenderer.Configuration) {
              // Configure other aspects of LayerRenderer
      
              let trackingAreasFormat: MTLPixelFormat = .r8Uint
              if capabilities.supportedTrackingAreasFormats.contains(trackingAreasFormat) {
                  configuration.trackingAreasFormat = trackingAreasFormat
              }
          }
      }
    • 7:54 - Object render function

      // Object render function
      
      extension MyObject {
          func render(drawable: Drawable, renderEncoder: MTLRenderCommandEncoder) {
              var renderValue: LayerRenderer.Drawable.TrackingArea.RenderValue? = nil
              if self.isInteractive {
                  let trackingArea = drawable.addTrackingArea(identifier: self.identifier)
                  if self.usesHoverEffect {
                      trackingArea.addHoverEffect(.automatic)
                  }
                  renderValue = trackingArea.renderValue
              }
      		self.draw(with: commandEncoder, trackingAreaRenderValue: renderValue)
          }
      }
    • 8:26 - Metal fragment shader

      // Metal fragment shader
      
      struct FragmentOut
      {
          float4 color [[color(0)]];
          uint16_t trackingAreaRenderValue [[color(1)]];
      };
      
      fragment FragmentOut fragmentShader( /* ... */ )
      {
          // ...
      
          return FragmentOut {
              float4(outColor, 1.0),
              uniforms.trackingAreaRenderValue
          };
      }
    • 10:09 - Event processing

      // Event processing
      
      extension Renderer {
          func processEvent(_ event: SpatialEventCollection.Event) {
             let object = scene.objects.first {
                 $0.identifier == event.trackingAreaIdentifier
             }
             if let object {
                 object.performAction()
             }
         }
      }
    • 13:08 - Quality constants

      // Quality constants
      
      extension MyScene {
          struct Constants {
              static let menuRenderQuality: LayerRenderer.RenderQuality = .init(0.8)
              static let worldRenderQuality: LayerRenderer.RenderQuality = .init(0.6)
              static var maxRenderQuality: LayerRenderer.RenderQuality { menuRenderQuality }
          }
      }
    • 13:32 - Layer configuration

      // Layer configuration
      
      struct MyConfiguration: CompositorLayerConfiguration {
          func makeConfiguration(capabilities: LayerRenderer.Capabilities,
                                 configuration: inout LayerRenderer.Configuration) {
             // Configure other aspects of LayerRenderer
      
             if configuration.isFoveationEnabled {
                 configuration.maxRenderQuality = MyScene.Constants.maxRenderQuality
             }
      }
    • 13:57 - Set runtime render quality

      // Set runtime render quality
      
      extension MyScene {
          var renderQuality: LayerRenderer.RenderQuality {
              switch type {
              case .world: Constants.worldRenderQuality
              case .menu: Constants.menuRenderQuality
              }
          }
      }
      
      extension Renderer {
          func adjustRenderQuality(for scene: MyScene) {
              guard layerRenderer.configuration.isFoveationEnabled else {
                  return;
              }
              layerRenderer.renderQuality = scene.renderQuality
          }
      }
    • 16:58 - SwiftUI immersion style

      // SwiftUI immersion style
      
      @main
      struct MyApp: App {
          @State var immersionStyle: ImmersionStyle
      
          var body: some Scene {
              ImmersiveSpace(id: "MyImmersiveSpace") {
                  CompositorLayer(configuration: MyConfiguration()) { @MainActor layerRenderer in
                      Renderer.startRenderLoop(layerRenderer)
                  }
              }
              .immersionStyle(selection: $immersionStyle, in: .progressive, .full)
          }
      }
    • 17:12 - Layer configuration

      // Layer configuration
      
      struct MyConfiguration: CompositorLayerConfiguration {
          func makeConfiguration(capabilities: LayerRenderer.Capabilities,
                                 configuration: inout LayerRenderer.Configuration) {
              // Configure other aspects of LayerRenderer
              
              if configuration.layout == .layered {
                  let stencilFormat: MTLPixelFormat = .stencil8 
                  if capabilities.drawableRenderContextSupportedStencilFormats.contains(
                      stencilFormat
                  ) {
                      configuration.drawableRenderContextStencilFormat = stencilFormat 
                  }
                  configuration.drawableRenderContextRasterSampleCount = 1
              }
          }
      }
    • 17:40 - Render loop

      // Render loop
      
      struct Renderer {
          let portalStencilValue: UInt8 = 200 // Value not used in other stencil operations
      
          func renderFrame(with scene: MyScene,
                           drawable: LayerRenderer.Drawable,
                           commandBuffer: MTLCommandBuffer) {
              let drawableRenderContext = drawable.addRenderContext(commandBuffer: commandBuffer)
              let renderEncoder = configureRenderPass(commandBuffer: commandBuffer)
              drawableRenderContext.drawMaskOnStencilAttachment(commandEncoder: renderEncoder,
                                                                value: portalStencilValue)
              renderEncoder.setStencilReferenceValue(UInt32(portalStencilValue))
              
              scene.render(to: drawable, renderEncoder: renderEncoder)
      
              drawableRenderContext.endEncoding(commandEncoder: commandEncoder)
              drawable.encodePresent(commandBuffer: commandBuffer)
          }
      }
    • 20:55 - App structure

      // App structure
      
      @main
      struct MyImmersiveMacApp: App {
          @State var immersionStyle: ImmersionStyle = .full
      
          var body: some Scene {
              WindowGroup {
                  MyAppContent()
              }
      
              RemoteImmersiveSpace(id: "MyRemoteImmersiveSpace") {
                  MyCompositorContent()
              }
              .immersionStyle(selection: $immersionStyle, in: .full, .progressive)
         }
      }
    • 21:14 - App UI

      // App UI
      
      struct MyAppContent: View {
          @Environment(\.supportsRemoteScenes) private var supportsRemoteScenes
          @Environment(\.openImmersiveSpace) private var openImmersiveSpace
          @State private var spaceState: OpenImmersiveSpaceAction.Result?
      
          var body: some View {
              if !supportsRemoteScenes {
                  Text("Remote SwiftUI scenes are not supported on this Mac.")
              } else if spaceState != nil {
                  MySpaceStateView($spaceState)
              } else {
                  Button("Open remote immersive space") {
                      Task {
                          spaceState = await openImmersiveSpace(id: "MyRemoteImmersiveSpace")
                      }
                  }
              }
          }
      }
    • 21:35 - Compositor content and ARKit session

      // Compositor content and ARKit session
      
      struct MyCompositorContent: CompositorContent {
          @Environment(\.remoteDeviceIdentifier) private var remoteDeviceIdentifier
      
          var body: some CompositorContent {
              CompositorLayer(configuration: MyConfiguration()) { @MainActor layerRenderer in
                  guard let remoteDeviceIdentifier else { return }
                  let arSession = ARKitSession(device: remoteDeviceIdentifier)
                  Renderer.startRenderLoop(layerRenderer, arSession)
              }
          }
      }
    • 23:17 - C interoperability

      // Swift
      let remoteDevice: ar_device_t = remoteDeviceIdentifier.cDevice
Renderer.start_rendering(layerRenderer, remoteDevice)
      
      // C
      void start_rendering(cp_layer_renderer_t layer_renderer, ar_device_t remoteDevice) {
    ar_session_t session = ar_session_create_with_device(remoteDevice);
    // ...
}
    • 0:00 - Introdução
    • A renderização com o Metal no visionOS, juntamente com os Compositor Services, traz recursos novos este ano, incluindo: efeitos de destaque em objetos interativos, qualidade de renderização dinâmica para o conteúdo, novo estilo de imersão progressiva e a capacidade de renderizar conteúdo imersivo no Vision Pro a partir do macOS.

    • 1:58 - Novas APIs de loops de renderização
    • Houve uma mudança no loop de renderização no visionOS. Em vez de retornar um recurso gráfico, o objeto queryDrawables retorna uma matriz com um ou dois recursos gráficos. O segundo recurso gráfico estará presente durante a gravação de um vídeo em alta qualidade com o Reality Composer Pro. Confira no Xcode um modelo para ajudar você a começar. O Metal e o Metal 4 são compatíveis.

    • 4:21 - Efeitos de foco
    • Depois de adotar a nova API de loop de renderização, comece a implementar efeitos de destaque nos objetos interativos. Com os efeitos de foco, as pessoas podem ver quais objetos são interativos e antecipar os alvos de suas ações. O sistema destacará dinamicamente o objeto que a pessoa estiver olhando. Um jogo de quebra-cabeça pode destacar as peças que o jogador pode selecionar. Para isso, use a nova textura de áreas de rastreamento, que define as diferentes regiões interativas na cena. Há algumas considerações adicionais se você estiver usando MSAA (multisample antialiasing).

    • 10:50 - Qualidade de renderização dinâmica
    • Você pode desenhar seu conteúdo com uma fidelidade ainda maior. Ao usar a qualidade de renderização dinâmica, você pode ajustar a resolução do conteúdo com base na complexidade das cenas. Ela se baseia na renderização foveada, priorizando a densidade de pixels onde o espectador está olhando. Defina a qualidade máxima de renderização e ajuste a qualidade em tempo de execução nesse intervalo. Qualidade mais alta melhora a clareza, mas aumenta o uso de memória e energia. Equilibrar qualidade e desempenho é fundamental. Encontre o equilíbrio com ferramentas como o Instruments e o depurador do Metal.

    • 14:44 - Imersão progressiva
    • Novidade este ano: renderize conteúdo dentro de um portal imersivo progressivo. Com isso, as pessoas controlam o nível de imersão girando a Digital Crown. Isso as conecta ao ambiente real e pode ajudar a proporcionar mais conforto na visualização de cenas complexas com movimento. Para implementar isso, o sistema deve fornecer um buffer de estêncil para mascarar o conteúdo fora dos limites do portal. O sistema aplica um efeito de esmaecimento nas bordas do portal, criando uma transição suave entre os ambientes real e renderizado. Os pixels fora da visão do portal não são renderizados, poupando poder de processamento. Os detalhes da implementação são compartilhados.

    • 18:32 - Renderização espacial para macOS
    • A renderização espacial no macOS permite aproveitar o poder do Mac para renderizar e transmitir conteúdo imersivo para o Apple Vision Pro. Esse recurso permite que apps Mac sejam aprimorados com experiências imersivas, como pré-visualizações em tempo real de modelagem 3D. O ARKit e o worldTrackingProvider agora estão disponíveis no macOS. Isso permite consultar a localização do Vision Pro no espaço. O RemoteImmersiveSpace do macOS hospeda o CompositorLayer e o ARKitSession, como um app nativo do visionOS faria. Há um novo remoteDeviceIdentifier que será usado para conectar a sessão ARKit do Mac ao Vision Pro. E todas as APIs relevantes têm equivalentes nativas em C.

    • 23:51 - Próximas etapas
    • Essas funcionalidades do Metal e dos Compositor Services no visionOS permitem oferecer melhor interatividade, maior fidelidade e o novo estilo de imersão progressiva aos apps e jogos. Confira “Defina a cena com SwiftUI no visionOS” e “Novidades do visionOS 26”.

Developer Footer

  • Vídeos
  • WWDC25
  • Novidades na renderização no Metal para apps imersivos
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines