Yes, realistically you can only add at most ~30 bits of security to a password. This does not save very poor passwords, but can save decent ones.
'Strong' means different things in different contexts. SHA-256, for example, is a strong hash function: it has good preimage and collision resistance. However, a function is evaluated by its weakest point: when given a low-entropy secret (which is not the assumption in a strong hash function) and a strong hash function, the easiest attack is to bruteforce it by sampling its distribution (e.g., the most common password patterns).
Since SHA-256 is fast, bruteforce is naturally also fast: the average time-to-break for a string of entropy s is 2^(s-1) times the cost of a SHA-256 evaluation. You can build on this by, say, iterating on SHA-256:
def pwdhash(input, salt, w):
h = sha256(salt + input).digest()
for i in range(2**w):
h = sha256(h).digest()
return h
But once you get into these ad hoc schemes to make the password hash less amenable to bruteforce, you're basically reinventing PBKDF2. scrypt (and bcrypt, to some extent) is like the above, but also uses random memory accesses on a large buffer to make things harder for specialized hardware (think GPUs, FPGAs, etc).