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 ↗Code shown on screen · 6 snippets
Hybrid rendering in Metal 1
// 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
// Create render pass
id< MTLRenderCommandEncoder > renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:gbufferPass];
encodeRenderScene( scene, renderEncoder );
[renderEncoder endEncoding]; Hybrid rendering in Metal 3
// 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
// 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
// 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
// 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
Related sessions
-
32 min -
34 min -
32 min -
30 min -
40 min -
21 min