Skip to content

Draw translucent dice as refracting resin - #376

Merged
drehtuer merged 3 commits into
rendering/galleryfrom
rendering/translucent-dice
Oct 5, 2026
Merged

drehtuer merged 3 commits into
rendering/galleryfrom
rendering/translucent-dice

Conversation

@drehtuer

@drehtuer drehtuer commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Step 3 on feature/realistic-rendering: translucent dice that look like resin.

Approach (decision 90): screen-space refraction, SOLID type, IOR 1.5, LIT shading with the clear coat kept.

  • Opaque blending: refraction needs it in Filament 1.76.
  • Replaces the blended material: nothing used that any more. The resin is still compiled lazily and cached like the others.
  • Subsurface model rejected: Filament compiles refraction out under SHADING_MODEL_SUBSURFACE, it has no clear coat, and it never shows what is behind the die.
  • Numbers and artwork stay opaque and crisp.
  • No format change: everything derives from translucency, color, size_mm and roughness. On a translucent die, roughness also frosts what is seen through it.

First device round: glassy dice came out black. Filament already tints the refracted sample by the base colour, and the material tinted it again through absorption, so the felt kept about a tenth of its colour.

Fixed:

  • The tint is applied once: the bare body moves towards √colour by as much light as passes through.
  • Absorption is dropped.
  • Transmission is now 1 − (1 − t)².

On the Pixel 10a:

  • FilamentStageTest passes 13/13.
  • New aGlassyDieTakesTheColourOfTheFloorUnderIt: 91 % of a clear die's body pixels take the floor's hue (bar 30 %).
  • The gallery shows the felt through the dice, bent across the facets; opaque and metal dice are unchanged.
  • The gallery gains a milky (0.2) and a glassy (1.0, roughness 0.05) scene.

Known limit, for the owner's judgement: Filament's shadow maps treat a resin die as opaque, so the felt seen through it is in its own full shadow, and glassy dice look dark.

Docs: docs/physics-and-rendering.md ("A die you can see into"), docs/dice-sets.md, decision 90.

Based on #375.

🤖 Generated with Claude Code

drehtuer and others added 3 commits October 4, 2026 17:03
The blended (TRANSPARENT) material drew a translucent die as a dusty,
faded opaque one: nothing behind it bent and nothing in it deepened.
A translucent die is now drawn with Filament's screen-space refraction
(SOLID, IOR 1.5, LIT with the clear coat kept), so the felt, its shadow
and the dice beside it show through, displaced and tinted, with the
colour deeper through the middle than at the edges.

The resin is a second material compiled on first use and cached like
the opaque one; it replaces the blended variant, which no die needed
any more. Refraction requires opaque blending in Filament, and the
SUBSURFACE model can neither refract nor carry a clear coat, so it is
not used. Printed numbers and artwork transmit nothing and keep the
author's roughness, so they stay crisp and opaque.

Every resin input is derived from fields a set already writes
(translucency, color, size_mm, roughness), so the dice-set format does
not change: transmission = translucency, the see-through blur is
max(roughness, 0.6 x (1 - translucency)) so low translucency reads
milky, thickness is 0.7 of the drawn size, absorption comes from the
colour. Opaque surfaces draw the same pixels as before: the only change
to their shader is dropping a multiply by a coverage that was always 1.

Decision 90 in docs/architecture.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Translucency 0.2 and 1.0 (with roughness 0.05) alongside the 0.6 scene,
so both ends of the resin material can be judged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Pixel 10a a glassy amber die came out near-black and a 0.6 one
read as opaque copper, with nothing of the felt visible in either.

The screen-space input was not empty: the existing device test already
saw 704 pixels of a cream die change between a red and a blue floor,
which an empty or black refraction buffer cannot produce. Filament
1.76.1's own evaluateRefraction (in the shader sources libfilamat
carries) gives the reason instead: it multiplies the refracted sample by
the base colour itself (Ft *= pixel.diffuseColor), and drops the body's
diffuse light by the transmission. The resin also passed an absorption
worked out from the same colour, so green felt (linear green 0.11) under
amber (0.22, and about half again from the absorption) kept a tenth of
its green, and that felt is in the die's own shadow. The absorption was
not buying depth either: a solid-sphere ray crosses between 0.75 and 1
of the thickness, so it was a uniform second tint.

So the absorption is gone and the bare body's base colour is moved
towards the square root of the die's colour by as much as passes
through: the colour a set writes is what a clear die looks like over a
pale table, which is two passes through it, so one pass is the root.
Green felt under amber is then olive rather than black.

Transmission is now 1 - (1 - translucency)^2 instead of translucency as
it stands. The body is lit by the key light while the felt it shows
lies in its shadow, so weighed linearly the felt was a few per cent of
a 0.6 die. 0.6 now lets 84 % through and 0.2 lets 36 %; both ends stay.

A new device test draws a near-white glass d20 over a red and then a
blue floor and requires at least 30 % of its body pixels to take each
floor's hue, logging the share under dinfinity.startup.

Docs: decision 90, "A die you can see into", dice-sets.md translucency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 4, 2026

Copy link
Copy Markdown

@drehtuer
drehtuer added this pull request to stack #386 October 5, 2026 06:37
@drehtuer
drehtuer merged commit 12ff4a7 into feature/realistic-rendering Oct 5, 2026
9 checks passed
@drehtuer
drehtuer deleted the rendering/translucent-dice branch October 5, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant