Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 Graphics & Games

WWDC21 · 30 min · Graphics & Games

Explore hybrid rendering with Metal ray tracing

Discover how you can combine ray tracing with your rasterization engine to implement simplified graphics techniques and elevate visuals in your app or game. We’ll explore how you can use natural algorithms to accurately simulate the interplays of light, and learn how to take advantage of the latest tools in Xcode to capture, inspect, and debug your ray-traced scenes.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 6 snippets

Hybrid rendering in Metal 1 objectivec · at 6:32 ↗
// Create render pass

MTLRenderPassDescriptor* gbufferPass = [MTLRenderPassDescriptor new];
gbufferPass.depthAttachment.texture = gbuffer.depthTexture;
gbufferPass.depthAttachment.storeAction = MTLStoreActionStore;

gbufferPass.colorAttachments[0].texture = gbuffer.normalTexture;
gbufferPass.colorAttachments[0].storeAction = MTLStoreActionStore;
Hybrid rendering in Metal 2 objectivec · at 6:50 ↗
// Create render pass

id< MTLRenderCommandEncoder > renderEncoder =
             [commandBuffer renderCommandEncoderWithDescriptor:gbufferPass];

encodeRenderScene( scene, renderEncoder );

[renderEncoder endEncoding];
Hybrid rendering in Metal 3 objectivec · at 7:06 ↗
// Dispatch ray tracing via compute

id< MTLComputeCommandEncoder > compEncoder = [commandBuffer computeCommandEncoder];

[compEncoder setTexture:gbuffer.depthTexture atIndex:0];
[compEncoder setTexture:gbuffer.normalTexture atIndex:1];

[compEncoder setTexture:outReflectionMap atIndex:2];

[compEncoder setComputePipelineState:raytraceReflectionKernel];

encode2dDispatch( width, height, compEncoder );

[compEncoder endEncoding];
Ray-traced shadow kernel objectivec · at 11:54 ↗
// Calculate shadow ray from G-Buffer

float3 p = calculatePosition( depth_texture, thread_id );
ray shadowRay( p, lightDirection, 0.01f, 1.0f );

// Trace for any intersections

intersector< triangle_data, instancing > shadowIntersector;
shadowIntersector.accept_any_intersection( true );

auto shadowIntersection = shadowIntersector.intersect( shadowRay, accel_structure );

// Point is in light if no intersections are found

if ( intersection.type == intersection_type::none ) {
   // Point is illuminated by this light
}
Ray-traced ambient occlusion kernel objectivec · at 15:07 ↗
// Generate ray in hemisphere

ray ray = cosineWeightedRay( thread_id );

ray.max_distance = 0.5f;

// Trace nearby intersections

intersector< triangle_data, instancing > i;

auto intersection = i.intersect( ray, accel_structure );

if ( intersection.type != intersection_type::none ) {
   // Point is obscured by nearby geometry
}
Ray-traced reflection kernel swift · at 19:34 ↗
// Calculate shadow ray from G-Buffer

float3 p = calculatePosition( depth_texture, thread_id );
float3 reflectedDir = reflect( p - cameraPosition, normal );

ray reflectedRay( p, reflectedDir, 0.01f, FLT_MAX );

// Trace for any intersections

intersector< triangle_data, instancing > refIntersector;
auto intersection = refIntersector.intersect( reflectedRay, accel_structure );

// Shade depending on intersection

if ( intersection.type != intersection_type::none ) {
   // Reflected ray hit an object: perform shading
}
else {
   // No intersection: draw skybox
}

Resources