Most of the complexity is from when UEFI and GPT were introduced. Let me define all the terms for you, then the process that ties them together:

A bootloader is what loads your OS. Alternatively, it can load another bootloader: for example, GRUB chainloading the windows bootloader. Even if a bootloader can support both BIOS and UEFI, it must install a matching configuration, because the UEFI boot process is structured very differently from the BIOS boot process. The bootloader also sets Linux kernel flags.

UEFI replaces BIOS. A UEFI will probably emulate the BIOS boot methodology with "legacy mode". These are basically the OS that loads your bootloader. One of the two lives on your motherboard and configures your hardware.

GPT replaces MBR. They are both partitioning schemes: they organize the areas in a storage media where a filesystem can exist. MBR has an overcomplicated partitioning scheme, and a few reserved sectors in the front that tell the BIOS where to find a bootloader. GPT has a simple partitioning scheme, and a special partition for the bootloader. BIOS does not support GPT. UEFI probably supports MBR with its legacy mode.

That special GPT bootloader partition is called the "EFI System Partition" (ESP). A partition is "flagged" as ESP in the GPT partition table itself. It is expected that an ESP partition will be formatted with the fat32 filesystem.

When using BIOS, Windows is infamous for overwriting the MBR to point to its bootloader.

When using UEFI, Windows install media autogenerates the ESP partition alongside multiple backup partitions: if there is an existing ESP partition on any present internal storage media, the windows installer will simply use that one, even if there isn't enough space. If there are multiple ESP partitions present, you cannot tell the windows installer which one to install to.

Since the MBR does most of the work, a BIOS only needs to decide which disk to boot. Usually it saves the order of disks that it will try. Some older BIOSes don't support booting USB media, but you can potentially work around this by loading another bootloader from a floppy/CD and chainloading.

UEFI saves a list of boot entries. It can autogenerate them by scanning storage media, like USB install disks. An OS can save or edit these entries directly, so long as it has been booted with permission (some laptop motherboards overcomplicate this). The Linux kernel can be compiled with a minimal EFIstub bootloader. In this case, the kernel flags are saved in the UEFI boot entry on the motherboard.

The boot sequence looks like this:

1. The BIOS or UEFI initializes hardware, and lets the user interrupt to edit BIOS/UEFI settings.

2a. UEFI has a saved list of boot entries. The default entry is loaded, or one is chosen from the list in the UEFI settings. The boot entry loads a bootloader, a Linux kernel EFIstub, or some arbitrary UEFI program like memtest86.

2b. BIOS must search all present disks for a bootloader. This is expected to be found in the first few sectors of the MBR partition table. The saved order of potentially bootable storage media is followed: the first bootloader found is loaded.

3. The bootloader does what it is configured to do. GRUB will usually present a list of entries configured by the OS it was installed with. The bootloader loads an OS.

There are some more complexities:

Libreboot/Coreboot is both a firmware (like UEFI) and a bootloader. It's made to skip as much hardware initialization as possible, and go straight to the OS fast.

Apple implements their own proprietary "EFI", which is like UEFI, but less compatible, and has a very minimal pre-OS UI. It (at my most recent attempts nearly a decade ago) refuses to boot USB media. The bootloader rEFInd is pretty necessary if you want multiple OS installs.

The world of ARM is different: no UEFI or BIOS. Usually whatever bootloader Android uses, but maybe [libre/core]boot.