Skip to content

Ground shadows: shape and placement controls (scale, offset, light direction) #1631

Description

@obiot

Follow-up to #1515, which shipped the blob shadow itself. Three related gaps surfaced while building a chase-camera 3D scene; parking them together to revisit.

Today Mesh._drawGroundShadow places the quad at the caster's own x/z:

out[12] = originX;
out[13] = groundY - extent * SHADOW_LIFT;
out[14] = originZ;

with an ellipse sized to the caster's footprint times a module-level SHADOW_SPREAD (1.2). So a blob is always centred under its caster, always the same relative size, and never influenced by where the light is.


1. Per-object shadow scale

shadowOpacity is per mesh; size is not — it comes from the footprint and a constant. There is no way to say "this character's shadow should read a little larger" or "this pickup's a little tighter".

This is the one with the best cost/benefit. A wide, flat-bottomed prop resting on the ground hides its own blob completely from a camera looking down at it — nothing is visibly wrong, there is simply no shadow — and a slightly larger blob resolves it with no lifting and no physical claims. Suggested shape: shadowScale (default 1), sitting next to shadowOpacity.

2. Author-supplied offset

shadowOffset as a world-space x/z the game sets, giving the sun-angle look without the engine inferring anything, and without needing to decide which light wins.

3. Offset derived from the light direction

The automatic version of (2): take the scene's dominant directional Light3d, project onto the ground plane, offset the blob and stretch its major axis along that vector.

Recorded with the reasons it was not done first, so it is not re-proposed without them being addressed:

  • the blob is a flat quad on one named plane, with no occlusion and no contact with terrain. An offset blob slides off the slope it is supposed to be lying on as soon as the ground is not flat.
  • a low sun should lengthen a shadow, which a footprint-sized ellipse cannot express — so the offset alone looks more wrong, not less.
  • it needs an arbitrary "which light wins" rule for a scene with several, plus a defined fallback when there is no directional light.
  • coupling it to a real light makes the blob look like it is modelling something, which invites scrutiny the model cannot survive. Direction-correct shadows want a shadow map, which is past the scope of this tier.

Also considered and rejected

Clamping or warning when shadowGroundY is lifted above the caster's base. It looks like a guard against a real trap — lifting the plane does not slide the blob out from under an object, it floats it up, and past a few units it projects over the top as a dark ring. But the same setting is legitimately used for a jumping or flying object whose shadow must stay on the floor and shrink with height, so a clamp would break the case the setting exists for. Documented in the melonjs-3d and melonjs-3d-assets skills instead (#1630).


All three default to current behaviour, so none is breaking.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions