impl Renderer { pubfn new(device: Device) -> Self { let scene = Scene::new(device.clone());
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("examples/raytracing/shaders.metallib"); let library = device.new_library_with_file(library_path).unwrap(); let queue = device.new_command_queue();
let buffer_data = [0u8; UNIFORM_BUFFER_SIZE as usize]; let uniform_buffer = device.new_buffer_with_data(
buffer_data.as_ptr() as *const c_void,
UNIFORM_BUFFER_SIZE,
get_managed_buffer_storage_mode(),
);
uniform_buffer.set_label("uniform buffer"); let resources_stride = { letmut max = 0; for geometry in &scene.geometries { let s = geometry.get_resources().len(); if s > max {
max = s;
}
}
max
}; letmut resource_buffer_data = vec![0u64; resources_stride * scene.geometries.len()]; for geometry_index in0..scene.geometries.len() { let geometry = scene.geometries[geometry_index].as_ref(); let resource_buffer_begin_index = resources_stride * geometry_index; let resources = geometry.get_resources();
for argument_index in0..resources.len() { let resource_buffer_index = resource_buffer_begin_index + argument_index; let resource = resources[argument_index].clone();
resource_buffer_data[resource_buffer_index] = if resource.conforms_to_protocol::<MTLBuffer>().unwrap() { let buffer = unsafe { Buffer::from_ptr(transmute(resource.into_ptr())) };
buffer.gpu_address()
} elseif resource.conforms_to_protocol::<MTLTexture>().unwrap() { let texture = unsafe { Texture::from_ptr(transmute(resource.into_ptr())) };
texture.gpu_resource_id()._impl
} else {
panic!("Unexpected resource!")
}
}
} let resource_buffer = device.new_buffer_with_data(
resource_buffer_data.as_ptr() as *const c_void,
(resource_buffer_data.len() * size_of::<u64>()) as NSUInteger,
get_managed_buffer_storage_mode(),
);
resource_buffer.set_label("resource buffer");
resource_buffer.did_modify_range(NSRange::new(0, resource_buffer.length()));
letmut primitive_acceleration_structures = Vec::new(); for i in0..scene.geometries.len() { let mesh = scene.geometries[i].as_ref(); let geometry_descriptor = mesh.get_geometry_descriptor();
geometry_descriptor.set_intersection_function_table_offset(i as NSUInteger); let geometry_descriptors = Array::from_owned_slice(&[geometry_descriptor]); let accel_descriptor = PrimitiveAccelerationStructureDescriptor::descriptor();
accel_descriptor.set_geometry_descriptors(&geometry_descriptors); let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor);
primitive_acceleration_structures.push( Self::new_acceleration_structure_with_descriptor(
&device,
&queue,
&accel_descriptor,
),
);
}
letmut instance_descriptors = vec![
MTLAccelerationStructureInstanceDescriptor::default();
scene.geometry_instances.len()
]; for instance_index in0..scene.geometry_instances.len() { let instance = scene.geometry_instances[instance_index].as_ref(); let geometry_index = instance.index_in_scene;
instance_descriptors[instance_index].acceleration_structure_index =
geometry_index as u32;
instance_descriptors[instance_index].options = if instance.geometry.get_intersection_function_name().is_none() {
MTLAccelerationStructureInstanceOptions::Opaque
} else {
MTLAccelerationStructureInstanceOptions::None
};
instance_descriptors[instance_index].intersection_function_table_offset = 0;
instance_descriptors[instance_index].mask = instance.mask as u32; for column in0..4 { for row in0..3 {
instance_descriptors[instance_index].transformation_matrix[column][row] =
*instance.transform.col(column).index(row);
}
}
} let instance_buffer = device.new_buffer_with_data(
instance_descriptors.as_ptr() as *const c_void,
(size_of::<MTLAccelerationStructureInstanceDescriptor>()
* scene.geometry_instances.len()) as NSUInteger,
get_managed_buffer_storage_mode(),
);
instance_buffer.set_label("instance buffer");
instance_buffer.did_modify_range(NSRange::new(0, instance_buffer.length()));
let accel_descriptor = InstanceAccelerationStructureDescriptor::descriptor();
accel_descriptor.set_instanced_acceleration_structures(&Array::from_owned_slice(
&primitive_acceleration_structures,
));
accel_descriptor.set_instance_count(scene.geometry_instances.len() as NSUInteger);
accel_descriptor.set_instance_descriptor_buffer(&instance_buffer); let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor); let instance_acceleration_structure = Self::new_acceleration_structure_with_descriptor(&device, &queue, &accel_descriptor);
letmut intersection_functions = BTreeMap::<String, Function>::new(); for geometry in &scene.geometries { iflet Some(name) = geometry.get_intersection_function_name() { if !intersection_functions.contains_key(name) { let intersection_function = Self::new_specialised_function_with_name(
&library,
resources_stride as u32,
name,
);
intersection_functions.insert(name.to_string(), intersection_function);
}
}
} let raytracing_function = Self::new_specialised_function_with_name(
&library,
resources_stride as u32, "raytracingKernel",
); let intersection_function_array: Vec<&FunctionRef> = intersection_functions
.values()
.map(|f| -> &FunctionRef { f })
.collect(); let raytracing_pipeline = Self::new_compute_pipeline_state_with_function(
&device,
&raytracing_function,
&intersection_function_array,
); let intersection_function_table_descriptor = IntersectionFunctionTableDescriptor::new();
intersection_function_table_descriptor
.set_function_count(scene.geometries.len() as NSUInteger); let intersection_function_table = raytracing_pipeline
.new_intersection_function_table_with_descriptor(
&intersection_function_table_descriptor,
); for geometry_index in0..scene.geometries.len() { let geometry = scene.geometries[geometry_index].as_ref(); iflet Some(intersection_function_name) = geometry.get_intersection_function_name() { let intersection_function = &intersection_functions[intersection_function_name]; let handle = raytracing_pipeline
.function_handle_with_function(intersection_function)
.unwrap();
intersection_function_table.set_function(handle, geometry_index as NSUInteger);
}
} let render_descriptor = RenderPipelineDescriptor::new();
render_descriptor
.set_vertex_function(Some(&library.get_function("copyVertex", None).unwrap()));
render_descriptor
.set_fragment_function(Some(&library.get_function("copyFragment", None).unwrap()));
render_descriptor
.color_attachments()
.object_at(0)
.unwrap()
.set_pixel_format(MTLPixelFormat::RGBA16Float); let copy_pipeline = device
.new_render_pipeline_state(&render_descriptor)
.unwrap();
let texture_descriptor = Self::create_target_descriptor(1024, 1024); let accumulation_targets = [
device.new_texture(&texture_descriptor),
device.new_texture(&texture_descriptor),
]; let random_texture = device.new_texture(&texture_descriptor);
let uniforms = unsafe {
&mut *((self.uniform_buffer.contents() as *mut u8)
.add(self.uniform_buffer_offset as usize) as *mut Uniforms)
};
let position = self.scene.camera.position; let target = self.scene.camera.forward; let up = self.scene.camera.up;
let forward = Vec3::normalize(target.xyz() - position.xyz()); let right = Vec3::normalize(Vec3::cross(forward, up.xyz())); let up = Vec3::normalize(Vec3::cross(right, forward));
let field_of_view = 45.0 * (std::f32::consts::PI / 180.0); let aspect_ratio = self.size.width as f32 / self.size.height as f32; let image_plane_height = f32::tan(field_of_view / 2.0); let image_plane_width = aspect_ratio * image_plane_height;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.