There is no need to make the salt hidden information or use a particularly strong function for it (which is really a way of trying to hide the information).
For one thing, security by obscurity gets you nothing. Remember, people have to log in, possibly over an insecure medium. The way this has worked forever is that the server provides the salt and the client computes the hash of the salted password. The server then checks that against what it has.
In many scenarios, an eavesdropper can listen in and "steal" the salt. if you computed the salt with a hidden function, that computation would have to take place in the client for the client to pass a hashed, salted password back to the server. An attacker can open up a copy of the client software and presto! The salt calculation algorithm is there for the reading.
Random salts are the way to go. Their only purpose is to defeat dictionary attacks. Speaking of which, a Rainbow Table is a particular implementation of a Dictionary Attack. What a random salt does is make sure that you have to brute force any password you want to crack.
Nothing can make it harder than brute force calculating all the hashed values for (salt+password) strings up to a given length with a given character set.
Now about dictionary attacks. Say you have an incomplete dictionary, like just common words from an actual dictionary. Or let's pick a really small dictionary, just words like "default" or "password" or "admin."
Without any salt, you can generate hashes of your words and scan the database seeing if ANYONE has one of these passwords. In many cases, you don't want a specific user cracked, just anyone.
With random salts, you must generate hashes containing every possible salt value for each of the words in your dictionary. The thing that adds security is the number of bits in the salt, not obfuscating the algorithm.