Parts with LocalTransparencyModifier set should still have shadows

I’d like for users to be able to see their own shadow while in first person. Practically every intended use case for LocalTransparencyModifier would benefit from this. It would also give developers a hacky way to force shadows. This behavior might not be guaranteed for future LightingTechnology types, but it would be really nice to have.

Currently I hide the user’s head in first person, but it looks strange for their shadow to have no head:
20221221_201527_112_RobloxStudioBeta
Third person:
20221221_201520_516_RobloxStudioBeta

If the engine kept track of LocalTransparencyModifier and preserved shadows, it would improve most first person person experiences and experiences that use “invisicam” systems. This is similar to part.CastShadow's behavior with respect to lighting and seems like a reasonable feature to implement. It would also give LocalTransparencyModifier a meaningful purpose beyond interoperability.

No new properties are being suggested. Just a change so part shadows don’t hide when LocalTransparencyModifier is set. If someone wants to hide these shadows they can assign part.CastShadow to false, or modify Transparency instead of LocalTransparencyModifier.

Use cases:

  • Character shadows visible in first person.
  • Interior shadows and lighting preserved for custom top-down perspectives that hide roofs. Stained glass lighting would also be preserved if a new lighting technology supports that effect.
  • The ability to force shadows on hidden parts in ways unrelated to camera scripts. This wouldn’t be the canonical purpose, but it’s a common feature request. It would be achieved locally by setting LocalTransparencyModifier to 1 on the client.
27 Likes

Never noticed this, but I see this being a huge flaw in some games. I agree that we should have a LocalShadowModifier property as well.

A separate property shouldn’t be needed. LocalTransparencyModifier’s only purpose is to locally hide objects, mainly related to camera obstructions like first person mode. It makes sense for shadows to be preserved on objects that are hidden for these reasons.

3 Likes

I use this property for other purposes including hiding occluded parts or letting players hide parts placed by other players because it has no interaction with the transparency property which can be changed by various sources. This property is named generically and is used generically. This would be a breaking change.

A more appropriate solution would be to e.g. revise the CastsShadow property to accept an enum for WhenVisible, Never, or Always.

Unlikely to happen I think, but IMO Roblox needs to rethink their design standards about when they build properties as exclusive booleans, especially when there is usage ambiguity involved.

8 Likes

Parts are probably the most commonly used instance type, so I don’t think it’s worth adding additional properties for this feature. Parts are already pretty bloated with state. Too much will cause lag and slow part creation, so the API should be kept lightweight. LocalTransparencyModifier is technically a redundant property, especially when you control all of the scripts that are modifying parts like for your use case. LocalTransparencyModifier was specifically added with Lua-based camera scripts in mind, and would never have been added otherwise.

It’s relatively easy to store the original transparency in an attribute and modify Transparency instead, or set the model’s parent to nil to hide or disable parts. This can be done client-side without affecting the server or other clients. I don’t think this would be a breaking change. The modified parts are still physically there with non-1 transparency, and it would only affect lighting. This change has the benefit of being compatible with most camera scripts without introducing any complexity to the developer-facing API.

“LocalTransparencyModifier” would still be an acceptable property name. It still does was it says, and the shadow behavior could be easily explained in the documentation. Physically, transparency should have an affect on a shadow’s appearance, and this can’t be expressed by an enum or boolean. LocalTransparencyModifier leaves the original transparency unmodified for this purpose.

For example, a stained glass window’s colorful shadow could be preserved while a player is inside a building with a custom top-down perspective.

I’m not sure about enum vs boolean generally. It depends on the case, but I agree somewhat, especially if there are multiple booleans with exclusive overlapping behaviors. I think there are a few cases throughout the API where new enums probably weren’t needed though.

2 Likes

Here’s my two problems with this:

  • They would have to make LocalTransparencyModifier Serialize + Replicate in order for it to work as expected, which shouldn’t be a problem for production games but may cause some artifacts for the studio draggers, which alter the BasePart’s LocalTransparencyModifier if I am not mistaken.

  • You would either have to keep it as a hidden property or expose it in the properties tab, which would make it awkward to work with either way.

Overall, this wouldn’t fix the issue with the completely disorganized API Roblox has for this and I think it would be best if they just added a ShadowBehavior enumeration and made CastShadow act as a hidden proxy to it.

This feature would show shadows regardless of LocalTransparencyModifier, that’s all. It doesn’t need to be a serialized feature.

I disagree with a ShadowBehavior property because it is unable to specify a transparency that the shadows should render at. Currently shadows don’t properly respect transparency, but they certainly could for future lighting technologies. Consider the stained glass example, where the shadows should depend on the part’s transparency.

We don’t need to add another serialized property/bitfield to the insane number of parts that get initialized across all of Roblox. We already have a LocalTransparencyModifier property that can achieve this feature. You could still achieve what you want client side with the behavior I’m suggesting; It just needs to be assigned from a local script, just like how camera scripts do it.

This feature request is for changing shadow rendering behavior with respect to LocalTransparencyModifier. The documentation can simply state “This property does not affect shadows.” No new properties or APIs are suggested.

2 Likes

I use LocalTransparencyModifier to hide stuff on the client side without worrying about the actual transparency value. Adding an extra Attribute for it feels like just adding a second LocalTransparencyModifier that’s just annoying to write constantly with Object:SetAttribute().

As other people said, I think having a ShadowBehaviour enumeration would be better as it has its uses.

Having a transparent part that always has a shadow would be cool along with having an opaque part without a shadow. Changing how LocalTransparencyModifier is not really ideal for some people’s use cases as it could be remedied with the enum system.

LocalTransparencyModifier is like a multiplier and not an actual transparency value. It is meant to add on top of transparency’s value for the client. Eg. Transparency / (LocalTransparencyModifier - Transparency) (Or, something like that. I can’t math rn)

Edit: Oh, it also doesn’t force us to be required to use constant script changes if the transparency is ever wanting to be changed

Please consider that a property like this would not be able to respect transparent shadows. There have been lighting demos made by Roblox engineers that showcase this. I am certain that an enum is not the correct solution for this reason. Forcing shadows out of nowhere doesn’t seem like like a use case worth adding extra properties, but showing shadows in first person is an extremely common use case worth supporting.

I have been on Roblox for 14 years, and I remember when LocalTransparencyModifier was implemented. It was added specifically so that the Lua camera script could make the local character invisible. We need to think 10+ years ahead. Shadows appearing in past projects is a minor bug you can fix, and it’s certainly worth the added functionality and long-term simplicity.

LocalTransparencyModifier adds no new functionality to BaseParts on its own. It only needs to exist so that developers don’t need to juggle transparency values when making things transparent client-side. Preserving LocalTransparencyModifier’s exact behavior because of it’s name is shortsighted in my opinion. It would still be a local transparency modifier. It simply wouldn’t modify the shadows like regular transparency does.

1 Like

I have been on Roblox for 10+ years. You didn’t really have to say that. How I essentially broke it off on was; “If the original purpose isn’t broken, don’t fix it”.

Why not just deprecate LocalTransparencyModifier entirely for a shadows enumeration? That would make more sense to do instead of changing something that will change a lot of people’s games from the past. Preserving old projects is something that I strive for and giving more easier access to stuff for beginners would be great.

Besides, LocalTransparencyModifier is not shown at all in the properties menu. Some people I know only found out about it recently.

It pretty much is just a secondary transparency for the client to modify how transparent an object is. I do agree on that.

I can see where you are coming from with this, but I also don’t understand why they don’t make an enum that can overwrite how you want shadows to behave on the part entirely without having to use a script to change the LocalTransparencyModifier for this effect. It also allows you to change how shadows behave on the server to replicate entirely to every client if you really wanted to.

Edit: The first part was me misinterpreting what you said. I’m sorry if I sounded aggressive there.
I do want to iterate that I don’t fully see a reason to change the feature without some sort of way to work around it without having to do the hacky solution. I don’t want my characters to have first-person shadows, but some may do. That’s why a suggestion for the alternative was mentioned with a possible deprecation of the original transparency modifier.
Besides, why not use the transparency value and have an enum for if you want the transparency to affect shadows or not?

I apologize for that. I felt like I was reiterating the same points to each response to this post.

Did you see what I mentioned about an enumeration not being able to support transparent shadows? Ideally a transparent colored part would have a transparent colored shadow, depending on transparency amount. This cannot be expressed with an enum! Adding first person shadows with an enum like this would be a headache. What combination of properties would you even use to achieve this? It’s not intuitive.

The old projects would not be destroyed in any way. They would just have shadows where the developer didn’t expect at the time. I care deeply about the long term future of Roblox and am willing to adapt to changes if it improves performance and overall functionality. I also care a lot about the sanity of Roblox engineers. More features is not always better, especially if we can make do more easily with fewer.

Let’s compare it to a past feature. Part surfaces are on the way out and no longer display or automatically join. This was not a backwards compatible change but it was deeply necessary as Roblox becomes a competitive engine+platform and less of a block-building game. Displaying shadows for parts with LocalTransparencyModifier is a small change in comparison.

I have had projects entirely stop working because of changes like PreloadAsync({assetId})PreloadAsync({instance}) and type(vector3) == "userdata"type(vector3) == "vector". I just write the fix and move on. Transparent shadow behavior doesn’t fundamentally break anything.

I would also argue that this change would better-preserve the functionality of forked camera scripts and “invisicam” modules, because they would not need to be changed to support shadows for first person characters or parts obstructing the camera.

I would argue an enumeration would make things more complicated for beginners. Transparent first person shadows would no longer work out of the box. We would need to implement hacks to get it to work the way we want.
Let’s say BasePart has a fixed complexity/feature budget. You can only cram so many features into it before it’s too slow for Roblox to be able to support a competitive number of models/parts compared to other engines. Additional complexity also makes it more difficult for Roblox engineers to support and optimize these objects.

1 Like

So, wait, this is what you are asking for:

  • Some way to turn on-off shadows despite transparency
  • Some way to control shadow transparency (When it gets added) despite the actual Transparency (i.e. an invisible part casting a half-transparent shadow), but also to somehow be tied to it ?

You’re saying that if they made LocalTransparencyModifier only affect the visibility of a BasePart and let Transparency tailor the shadow’s transparency, both are solved.

But LocalTransparencyModifier is a modifier; it multiplies the Transparency value, not overrides it. What would the shadow’s transparency be when Transparency is 0.5 and LocalTransparencyModifier is 0.5? Would the shadow be 1/2 transparent or 3/4 transparent?

That’s why I think an enumeration is better (And more scaleable). You could add multiple behaviors for ShadowBehavior like CustomBehavior and expose new properties to control the shadow’s rendering (i.e. ShadowTransparency and possibly a ShadowColor). Changing LocalTransparencyModifier would not allow for that kind of freedom.

I’m not asking for any new properties or changes to how transparency multiplies. Just an internal change to how shadows render when objects have LocalTransparencyModifier set.
For example, a part where Transparency=0 and LocalTransparencyModifier=1, the part would be invisible but you would see its shadow.
If Transparency=0.5 and LocalTransparencyModifier=0.5, it would appear with a transparency of 0.25, but its shadows would appear with a transparency of 0.5.

You can’t specify the shadow’s transparency with an enum. Multiple shadow behaviors sounds like an engineer’s nightmare.

1 Like

I can see where you are getting at now. I do think that there should be some way to change the value of shadow transparency for a part. I don’t know if LocalTransparencyModifier's name would fit the purpose you are looking for, though. I would have considered having values with the name “Shadow Transparency” and “Shadow Color” to reduce confusion.

LocalTransparencyModifier does seem like something that should be deprecated for the replacements of ShadowTransparency (Float), ShadowColor (Color3), ColorEffectsShadow (Boolean), and ShadowBlur (Float) for more customization options for your use cases.

You can technically achieve this in the future with my proposed behavior change. You would just need 2 parts, where one has CastShadow=false, and the other has LocalTransparencyModifier=1. It would be set from a local script, which is fine.
Having fewer properties is more scalable because parts use less memory and have less data to save.

The transparency would still be modified with the same formula. The only difference is that shadows would no longer be unaffected by it. It would still modify the transparency locally and thus be a valid name. The name is already verbose and I don’t think it needs to be any more descriptive.

I think this would be a property of the part material specifically, independent from shadows. In real life the shadow color/behavior is derived from how light passes through it. A red window pane lets red light through. This behavior makes sense, is simple, and is worth preserving. Anything else is unintuitive in my opinion. How light diffuses through the material could be a proposed feature after this type of lighting is supported on high end devices, but it’s not related to shadows or LocalTransparencyModifier.

1 Like

That sounds like something that requires unnecessary constant syncing for moving parts (unless through welding), causing it to possibly require more memory and data for nonstatic objects.

Actually, sounds like a better idea than values on the part.

It does, and this is fine. You’re overriding the shadow a material casts. Normally this shouldn’t even be supported. A red window pane should let red light through. This would be a hacky workaround to get blue light to show through a red window pane. I don’t think it needs to be easy to do.

This is mostly speculative as Roblox doesn’t even support colored or transparent shadows even on the Future lighting technology (as far as I know.) Features should be designed with the rendering capabilities of future devices in mind though.

1 Like

Ah, that makes more sense. Thanks for the example as it definitely helped me understand what you could do with the method you suggested.

Oh, the Future technology doesn’t support coloured or transparent shadow. You are correct about that. It definitely is something I am looking forward to.

1 Like

I’ve also been on Roblox for over a decade, and I can also remember what you’re saying being the case, in relation to the LocalTransparencyModifier property.

I remember when it first came out, I was quite excited to see what I could do with it in future.
I eventually forgot about it after the hype died down but it still has a place in my memory haha.

I propose a more simple solution;

“A client only boolean property called LocalTransparencyShadows”

True (non default) would make it so that regardless of the other LT property’s value, shadows would display, and False (default), the LT shadows would only show if the part was in full view.

Hope this helps come up with a more logical solution :+1:

1 Like

This is a more complex solution because it requires introducing a new property that serializes.
If we really needed to preserve backwards compatibility for this, I would prefer a property of Lighting or Workspace that can only be edited while in studio that affects all parts. In the future it could be removed once developers had time to adapt.

I mentioned a few times above that we shouldn’t haphazardly add new properties to BasePart, for performance reasons and development simplicity for both us and Roblox engineers. I think the shadow behavior I suggested is intuitive and would give us the shadow features we want with minimal backwards compatibility concerns and no new properties. It seems I may not have explained it clearly enough in the original post though.

1 Like