Skip to main content
Glama

contact_shadow

Darken pixels where one form touches another along a colour ramp, adding a line one or two steps darker so an object does not appear to float.

Instructions

Darken the pixels where one form meets another, along its ramp.

Ambient occlusion as pixel artists actually draw it: a line one or two steps darker
where two shapes touch. It is what stops a shaded object looking like it is floating
in front of the thing it is standing on.

Args:
    ramp: Colours darkest first. Darkened pixels stay on this ramp.
    occluder_color: The colour of the form casting the occlusion, for example the
        ground a character stands on, or the blade a crossguard meets.
    radius: How far the darkening reaches from the occluder, in pixels. 1 or 2 is
        usually right; beyond that it reads as a drop shadow rather than contact.
    depth: How many ramp steps darker, at the contact line. 1 is the common choice.
    direction: Degrees, restricting occlusion to one side. Omit for all directions,
        which is what you want for a contact line; set it when only one side of the
        form is actually touching something.
    tolerance: How close a pixel must be to a ramp entry to be darkened. Pixels
        further away are left alone, so this does not spill onto other materials.
    occluder_tolerance: How close a pixel must be to `occluder_color` to count as the
        occluder, as a weighted RGB distance. Defaults to `tolerance`, which is what
        this did before it was a separate argument. It wants to be **tight**: the
        occluder is a flat fill you named, while `tolerance` has to stay loose enough
        for shaded art that varies, and one number cannot be both. At the shared
        default of 24 a ground colour within 24 of the subject's own ramp makes the
        subject its own occluder: measured on a 24x24 sprite with a subject painted
        `#5a5a7a` and ground `#60607e`, `occluder_pixels` came back as 312 (the 144
        ground pixels plus all 168 of the subject) and nothing was darkened at all.
        The result carries a warning naming any ramp entry this cannot be told apart
        from, because that overlap is invisible otherwise.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

Refuses a pass that darkened nothing rather than reporting `darkened_pixels: 0` as a
success, and the refusal carries the three counts that say which of the possible
causes it was. A contact shadow that changed no pixel is not a contact shadow.

Run this **before** the passes that repaint the occluder, not after. The occluder is
found by colour, so a `shade_region_by_light` or `shift_along_ramp` that has already
moved the ground off `occluder_color` leaves this matching a handful of pixels and
reporting the handful as a success.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rampYes
depthNoDefault: 1.
frameNoDefault: 1.
layerNo
radiusNoDefault: 1.
filenameYes
directionNo
toleranceNoDefault: 24.0.
occluder_colorYes
occluder_toleranceNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv0.10.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false (a write operation) but the description goes far beyond: it explains the tool's refusal behavior ('Refuses a pass that darkened nothing... the refusal carries the three counts'), it explains the warning about ambiguous ramp entries, and it describes the exact failure mode when occluder_tolerance is too loose (with a concrete example and numbers). This is exceptional transparency for a mutation tool, adding significant value beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear opening statement, parameter-by-parameter explanations, and a final usage-ordering rule. However, it is quite long and the occluder_tolerance paragraph is dense and somewhat rambling. It remains front-loaded with the core purpose, but the length and detail level, while useful, could be trimmed slightly without losing value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 10 parameters, low schema coverage, no output schema, and the tool's mutation nature, the description covers everything an agent needs: purpose, parameter semantics, behavioral quirks (refusal, warning), and ordering constraints. There are no significant gaps for correct invocation. It is complete and self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 40% (many parameters lack schema descriptions), so the description must carry the burden. It does so thoroughly: it explains each parameter's meaning, provides guidance for values (radius: '1 or 2 is usually right'), explains defaults and interactions (occluder_tolerance defaults to tolerance and why it should be tight), and gives a concrete example of misconfiguration. This fully compensates for the sparse schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and effect ('Darken the pixels where one form meets another, along its ramp') and elaborates with an analogy that leaves no ambiguity about what the tool does. Sibling tools include cast_shadow, glow, and add_drop_shadow, and the description explicitly distinguishes contact shadow from drop shadow ('beyond that it reads as a drop shadow rather than contact'). An agent can select this tool with confidence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use the tool ('Run this before the passes that repaint the occluder') and what not to do ('not after'). It also explains the failure mode of using it after other passes. It distinguishes the tool from related operations by warning about ordering relative to shade_region_by_light and shift_along_ramp. This is as good as it gets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools