The Sims 2 Legacy Collection: shadow fix
The rerelease of The Sims 2 introduced a fix for the black rectangles under Sims. You may have experienced this bug in the Ultimate Collection version.
As the creator of the Sims Shadow Fix, I was curious to know how it was done. But first, I'd like to explain what the problem with Sim shadows is.
What's the cause of the shadow bug?
When the game works as intended, a Sim shadow texture is a light bluish blob on a white background. It also has transparency, but it's unused. It looks like this:
However, many modern graphics cards render the texture as plain black with transparency:
That's why black rectangles appear under the Sims.
What does my mod do?
My mod is only a workaround for the bug. It uses the transparency to recreate the shadows.
The first versions released in 2015 and 2016 were achromatic, while the original shadows were bluish. Back then I didn't even know why and how my mod worked.
On 2 January 2025 I released new versions based on my research into shaders. I also recreated the original bluish shadows.
How does the Legacy Collection fix the shadow bug?
Thanks to @ivycopur I was able to examine the code. It uses a workaround, just like my mod.
In fact, it looks almost exactly like the really not misty 0.4 version of my mod, which, ironically, is now legacy. The shader code in the Legacy Collection contains the same nonsense. And a bit more.
Code comparison
The left side is the original code extracted from the Materials.package file in The Sims 2 Ultimate Collection. The right side is my code or the Legacy Collection code:
The differences between my code and the LC code:
- the debug part: I removed it from my code as players will never see it. The LC has this feature untouched.
- alphaBlend srcFactor: despite the difference, it actually changes nothing. Explained later.
The identical changes:
- alphaBlend dstFactor,
- the same colorScalar has been added,
- textureBlend.
Nonsense #1: textureBlend
The textureBlend defines how the colors of the incoming texture are transformed. The first argument is responsible for the color channels, the second – for the transparency.
Originally it's just:
And it means that the texture is taken as it is.
My and LC code transforms it though. The colorScalar is defined as a partially opaque (40%) black color. The transparency argument takes the transparency of the original texture and darkens it with the 40% factor:
And this makes sense. The color channels argument takes the transparency part of the texture and makes it pure black, because the color scalar is black:
It's pointless. I could go:
instead. It would be effectively the same.
The texture after the transformations looks like this:
Nonsense #2: alphaBlend
The alphaBlend defines how to mix the source colors (in this case the transformed texture from the textureBlend step) with the destination colors (in this case, the ground under Sim's feet).
The srcFactor argument defines the source color transformations, the dstFaction – defines the destination color transformations. And then they're put together.
Originally it's:
The srcFactor says that the shadow colors are darkened with the ground colors. The dstFactor doesn't really matter because it's multiplied by zero (black). Also, transparency isn't used.
If I understand correctly, you could achieve the same effect with:
And the final effect is:
My and LC code had to do it differently. The dstFactor says to darken the floor color with inverted transparency:
It sounds complicated, but the inversion actually means that black becomes white and vice versa. So the transparency texture, which is a dark gray blob on a black background, becomes a light gray blob on a white background.
The srcFactor is actually useless because the shadow texture (from the textureBlend step) is black. So it doesn't matter if you use:
like I did, or:
as in the LC code, it will always be black because you can't make black any darker. To make the intention clear, I'd personally go with:
instead. The final effect would always be:
It's different from the original intended effect. You can even see the difference in the official screenshots:
Conclusion
It doesn't look like a coincidence. The cause of the shadow bug hasn't been fixed, and I doubt that an experienced shader creator would come up with such a workaround. There are better ways.
Before you point out that it's against my terms of use to take my code and sell it, especially without credit, hear out. It doesn't matter – EA's policy allows it. And I'm not even angry. It's just funny that they trusted such a messy code. I wouldn't be surprised to see other creators' fixes in the Legacy Collection.
The good thing is that EA has addressed the shadow issue at all. 🙃