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
  • Código
  • Your guide to Metal ray tracing

    Discover how you can enhance the visual quality of your games and apps with Metal ray tracing. We'll take you through the fundamentals of the Metal ray tracing API. Explore the latest enhancements and techniques that will enable you to create larger and more complex scenes, reduce memory usage and build times, and efficiently render visual content like hair and fur.

    Capítulos

    • 0:09 - Intro
    • 1:50 - Build your scene
    • 9:48 - Scale with instancing
    • 17:34 - Build with parallelization
    • 18:34 - Refitting
    • 19:47 - Compaction
    • 21:14 - Intersect rays
    • 26:16 - Debug and profile
    • 30:42 - Wrap-Up

    Recursos

    • Rendering reflections in real time using ray tracing
    • Accelerating ray tracing using Metal
    • Metal for Accelerating Ray Tracing
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    Tech Talks

    • Discover new Metal profiling tools for M3 and A17 Pro
    • Explore GPU advancements in M3 and A17 Pro
    • Learn performance best practices for Metal shaders

    WWDC22

    • Maximize your Metal ray tracing performance

    WWDC21

    • Enhance your app with Metal ray tracing
    • Explore hybrid rendering with Metal ray tracing

    WWDC20

    • Discover ray tracing with Metal
  • Buscar neste vídeo...
    • 3:06 - Create triangle geometry descriptor

      // Create geometry descriptor:
      let geometryDescriptor = MTLAccelerationStructureTriangleGeometryDescriptor()
      
      geometryDescriptor.vertexBuffer = vertexBuffer
      geometryDescriptor.indexBuffer = indexBuffer
      geometryDescriptor.triangleCount = triangleCount
    • 3:20 - Create bounding box geometry descriptor

      // Create geometry descriptor:
      let geometryDescriptor = MTLAccelerationStructureBoundingBoxGeometryDescriptor()
      
      geometryDescriptor.boundingBoxBuffer = boundingBoxBuffer
      geometryDescriptor.boundingBoxCount = boundingBoxCount
    • 6:42 - Create curve geometry descriptor

      let geometryDescriptor = MTLAccelerationStructureCurveGeometryDescriptor()
        
      geometryDescriptor.controlPointBuffer = controlPointBuffer
      geometryDescriptor.radiusBuffer = radiusBuffer
      geometryDescriptor.indexBuffer = indexBuffer
      
      geometryDescriptor.controlPointCount = controlPointCount
      geometryDescriptor.segmentCount = segmentCount
      geometryDescriptor.curveType = .round
      geometryDescriptor.curveBasis = .bezier
      geometryDescriptor.segmentControlPointCount = 4
    • 7:29 - Create primitive acceleration structure descriptor

      // Create acceleration structure descriptor
      let accelerationStructureDescriptor = MTLPrimitiveAccelerationStructureDescriptor()
      
      // Add geometry descriptor to acceleration structure descriptor
      accelerationStructureDescriptor.geometryDescriptors = [ geometryDescriptor ]
    • 8:08 - Query for acceleration size and alignment requirements

      // Query for acceleration structure sizes
      let sizes: MTLAccelerationStructureSizes
      sizes = device.accelerationStructureSizes(descriptor: accelerationStructureDescriptor)
      
      // Query for size and alignment requirement in a heap
      let heapSize: MTLSizeAndAlign
      heapSize = device.heapAccelerationStructureSizeAndAlign(size: sizes.accelerationStructureSize)
    • 8:39 - Allocate acceleration structure and scratch buffer

      // Allocate acceleration structure from heap
      var accelerationStructure: MTLAccelerationStructure!
      accelerationStructure = heap.makeAccelerationStructure(size: heapSize.size)
      
      // Allocate scratch buffer
      let scratchBuffer = device.makeBuffer(length: sizes.buildScratchBufferSize,
                                            options: .storageModePrivate)!
    • 8:40 - Encode the acceleration structure build

      let commandEncoder = commandBuffer.makeAccelerationStructureCommandEncoder()!
      
      commandEncoder.build(accelerationStructure: accelerationStructure,
                           descriptor: accelerationStructureDescriptor,
                           scratchBuffer: scratchBuffer,
                           scratchBufferOffset: 0)
      
      commandEncoder.endEncoding()
    • 11:30 - Create instance acceleration structure descriptor

      var instanceASDesc = MTLInstanceAccelerationStructureDescriptor()
      
      instanceASDesc.instanceCount = ...
      instanceASDesc.instancedAccelerationStructures = [ mountainAS, treeAS, ... ]
      instanceASDesc.instanceDescriptorType = .userID
    • 12:07 - Allocate the instance descriptor buffer

      let size = MemoryLayout<MTLAccelerationStructureUserIDInstanceDescriptor>.stride
      let instanceDescriptorBufferSize = size * instanceASDesc.instanceCount
      
      let instanceDescriptorBuffer = device.makeBuffer(length: instanceDescriptorBufferSize,
                                                       options: .storageModeShared)!
          
      instanceASDesc.instanceDescriptorBuffer = instanceDescriptorBuffer
    • 12:33 - Populate instance descriptors

      var instanceDesc = MTLAccelerationStructureUserIDInstanceDescriptor()
      
      instanceDesc.accelerationStructureIndex = 0    // index into instancedAccelerationStructures
      instanceDesc.transformationMatrix = ...
      instanceDesc.mask = 0xFFFFFFFF
    • 14:06 - Configure indirect instance acceleration structure descriptor

      var instanceASDesc = MTLIndirectInstanceAccelerationStructureDescriptor()
      
      instanceASDesc.instanceDescriptorType = .indirect
      instanceASDesc.maxInstanceCount = ...
      instanceASDesc.instanceCountBuffer = ...
      instanceASDesc.instanceDescriptorBuffer = ...
    • 14:29 - Populate indirect instance descriptor

      device MTLIndirectAccelerationStructureInstanceDescriptor *instance_buffer = ...;
      // ...
      acceleration_structure<> as = ...;
      instance_buffer[i].accelerationStructureID = as;
      instance_buffer[i].transformationMatrix[0] = ...;
      instance_buffer[i].transformationMatrix[1] = ...;
      instance_buffer[i].transformationMatrix[2] = ...;
      instance_buffer[i].transformationMatrix[3] = ...;
      instance_buffer[i].mask = 0xFFFFFFFF;
    • 19:22 - Update geometry using refitting

      // Allocate scratch buffer
      let scratchBuffer = device.makeBuffer(length: sizes.refitScratchBufferSize,
                                            options: .storageModePrivate)!
      
      // Create command buffer/encoder ...
      
      // Refit acceleration structure
      commandEncoder.refit(sourceAccelerationStructure: accelerationStructure,
                           descriptor: asDescriptor,
                           destinationAccelerationStructure: accelerationStructure,
                           scratchBuffer: scratchBuffer,
                           scratchBufferOffset: 0)
    • 20:24 - Use compaction to reclaim memory

      // Use compaction to reclaim memory
      
      // Create command buffer/encoder ...
      
      sizeCommandEncoder.writeCompactedSize(accelerationStructure: accelerationStructure,
                                            buffer: sizeBuffer,
                                            offset: 0,
                                            sizeDataType: .ulong)
      
      // endEncoding(), commit command buffer and wait until completed ...
      
      // Allocate new acceleration structure using UInt64 from sizeBuffer ...
      
      compactCommandEncoder.copyAndCompact(sourceAccelerationStructure: accelerationStructure,
                                   destinationAccelerationStructure: compactedAccelerationStructure)
    • 21:36 - Set acceleration structure on the command encoder

      encoder.setAccelerationStructure(primitiveAccelerationStructure, bufferIndex:0)
    • 21:48 - Intersect rays with primitive acceleration structure

      // Intersect rays with a primitive acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<> i;
      
        ray r(origin, direction);
      
        intersection_result<> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
      
      
          // shade triangle...
        }
      }
    • 22:24 - Use triangle_data tag to get triangle barycentric coordinates

      // Intersect rays with a primitive acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<triangle_data> i;
      
        ray r(origin, direction);
      
        intersection_result<triangle_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
          float2 coords = result.triangle_barycentric_coord;
      
          // shade triangle...
        }
      }
    • 22:51 - Set instance acceleration structure on the command encoder

      encoder.setAccelerationStructure(instanceAccelerationStructure, bufferIndex:0)
      encoder.useHeap(accelerationStructureHeap);
    • 23:07 - Intersect rays with instance acceleration structure

      // Intersect rays with an instance acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<instancing> as, /* ... */) {
        intersector<instancing, max_levels<3>> i;
      
        ray r(origin, direction);
      
        intersection_result<instancing, max_levels<3>> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
      
          // shade triangle...
        }
      }
    • 24:43 - Find intersected instance information in the intersection result

      // Intersect rays with an instance acceleration structure
      
      [[kernel]]
      void trace_rays(acceleration_structure<instancing> as, /* ... */) {
        intersector<instancing, max_levels<3>> i;
      
        ray r(origin, direction);
      
        intersection_result<instancing, max_levels<3>> result = i.intersect(r, as);
      
        if (result.type == intersection_type::triangle) {
          float distance = result.distance;
          for (uint i = 0; i < result.instance_count; ++i) {
            uint id = result.instance_id[i];
            // ...
          }
          // shade triangle...
        }
      }
    • 25:02 - Intersect rays with curve primitives

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
      
        ray r(origin, direction);
      
        intersection_result<> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          // shade curve...
        }
      }
    • 25:26 - Find curve parameter in the intersection result

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<curve_data> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
      
        ray r(origin, direction);
      
        intersection_result<curve_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          float param = result.curve_parameter;
          // shade curve...
        }
      }
    • 26:04 - Set geometry type on the intersector for better performance

      // Intersect rays with curve primitives
      
      [[kernel]]
      void trace_rays(acceleration_structure<> as, /* ... */) {
        intersector<curve_data> i;
      
        i.assume_geometry_type(geometry_type::curve | geometry_type::triangle);
        i.assume_curve_type(curve_type::round);
        i.assume_curve_basis(curve_basis::bezier);
        i.assume_curve_control_point_count(3);
      
        ray r(origin, direction);
      
        intersection_result<curve_data> result = i.intersect(r, as);
      
        if (result.type == intersection_type::curve) {
          float distance = result.distance;
          float param = result.curve_parameter;
          // shade curve...
        }
      }

Developer Footer

  • Vídeos
  • WWDC23
  • Your guide to Metal ray tracing
  • 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