Semantically, Options and nullable types are pretty similar. Option<T> and T? work pretty much the same. There are some differencedifferences like explicit Some and methods that operate on options. But you indicate that's not what you are interested in. Rather, you seem more interested in the implementation detail of using null pointers rather then some sort of enum.
In a language like Rust, nullable pointers wouldn't work, because Rust doesn't have the indirection of a language like Java.
In Java, an ArrayList<String> is actually a pointer to an ArrayList object which contains a pointer to a String[] which is a pointer to an array of pointers to String objects each of which contains a char[] which is a pointer to an array of chars.
In Rust, a Vec<String> contains a pointer to an array of String each of which contains a pointer to a u8 array.
Consequently, in Rust, itsit is relatively rare that I want an Option<&T>. Most of the things that I want to have optional aren't references. For example, I often have an Option<String> but unlike in Java, String isn't a pointer to a String, it is a String.
Another way of looking at this, most types in Rust are value types not reference types. Thus nullable versions of those types couldn't be implemented as null pointers. They'd have to implemented as a value with a flag, which is how enums are implemented.
But the Rust compiler does have an optimization on this point. The easy case is Option<&T>, which can be implemented as a null pointer. But as noted, that's not actually very common. But the Rust compiler also looks inside the type to see if there is a non-nullable pointer inside. If compiling Option<String>, it see that String contains Vec<u8> which contains RawVec<u8> which contains Unique<u8> which contains NonZero<*u8>. The compiler knows that NonZero can never contain a null pointer, so it sets that field deep inside the String to null to indicate that the Option is None.
The consequence is that nullable pointer types wouldn't work for a language like Rust. Optional timestypes with compiler optimization does.
Furthermore, this is a relatively obvious optimization. I suspect that all languages with optional types that care about performance will ensure it gets implemented as a null pointer when that is suitable. So, there is no performance reason to shy away from Optional types in favor of nullables.