Skip to content

Glass catalog, absorption, temperature, colour, and the site - #2

Open
levvs-one wants to merge 32 commits into
mainfrom
design/glass-catalog
Open

Glass catalog, absorption, temperature, colour, and the site#2
levvs-one wants to merge 32 commits into
mainfrom
design/glass-catalog

Conversation

@levvs-one

@levvs-one levvs-one commented Sep 5, 2026

Copy link
Copy Markdown
Owner

What this adds

Core (Caustikon)

  • IDispersionModel, implemented by every model; generic consumers stay allocation-free.
  • Sellmeier (offset + up to eight terms, negative resonances accepted), Polynomial (n²) and Cauchy (n) with arbitrary exponents: the three closed forms manufacturer catalogs use.
  • Dispersion.EvaluateNanometers<T> batch helper with the buffer contract; Dispersion.ClassifyWavelength.

Catalog (Caustikon.Glasses, new package)

  • 1646 glasses from SCHOTT, OHARA, HOYA, CDGM, HIKARI, SUMITA, VITRON, Cargille and Amorphous Materials, generated from the RefractiveIndex.INFO database (CC0 1.0) by tools/Caustikon.Glasses.Generator. Data of record with one provenance record per glass under data/glasses/; fit deviations in manifest.json.
  • Typed vendor fields (Schott.NBK7 is a Sellmeier value) for the hot path; GlassCatalog.Find for name lookup; Glass.Define for caller-defined glass.
  • TabulatedExtinction → absorption and internal transmittance at any path length; ThermalDispersion (SCHOTT form) → absolute index shift; GlassColour → CIE XYZ and sRGB under D65.

Verification

  • Every catalogued glass checked at the exact d, F, C lines against its printed nd (5e-5 + printed rounding) and Vd (propagated bound); provenance completeness; name resolution.
  • N-BK7 pinned to the SCHOTT datasheet of 2023-12-01: seven τi rows at 10 and 25 mm, nine dn/dT cells; D65 white reproduced.
  • 155 core tests + 37 catalog tests; CI runs both packages on both frameworks and packs both.

Site (site/Caustikon.Site, Blazor WebAssembly)

  • Catalog with search and filters, a page per glass (index curve, τi at chosen thickness, transmitted colour, temperature, coefficients, provenance), a playground (interface + slab), formulas, about.
  • /use: for a chosen glass and thickness, CSS custom properties and a panel class (tint, Fresnel edge and face, refraction shift and fringe), GLSL with the glass's own dispersion formula, RGB index, absorption per millimetre and exact Fresnel, and the C# calls — every number from the catalog entry. Render light is adjustable; phones no longer scroll sideways.
  • pages.yml deploys to GitHub Pages on pushes to main; Pages is already enabled with the Actions source. The same build is also live on hel1 as caustikon.levvs.cc once its DNS record exists.
  • release.yml packs and pushes to NuGet.org on a v* tag once NUGET_API_KEY is set.

After merging

  1. Pages deploys automatically to https://levvs-one.github.io/caustikon/.
  2. Add the NUGET_API_KEY secret, then git tag v0.1.0 && git push --tags to publish both packages.

🤖 Generated with Claude Code

levvs and others added 4 commits September 5, 2026 23:11
Records the decisions taken in review: a separate Caustikon.Glasses package,
a boxing-free model abstraction in the core, generated-and-committed catalog
data under CC0, verification against vendor-published indices, and a roadmap
for colour and an interactive visualiser as later stages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…and Cauchy forms

IDispersionModel lets consumers stay generic over value-type models without
boxing. Sellmeier holds an offset and up to eight resonance terms, accepting the
negative resonances some catalog fits carry; Polynomial and Cauchy hold up to
eight power terms with arbitrary exponents and evaluate even integer powers by
repeated multiplication on the coefficient, so a tiny wavelength cannot overflow
an intermediate. Sellmeier3 and Cauchy3 implement the interface unchanged.

Dispersion.EvaluateNanometers<T> carries the batch buffer contract for every
model. New tests pin the general forms to the fixed ones bit for bit, to CDGM
BAF2's catalog nd and Vd, and to a zero-allocation generic call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ption, temperature and colour

A generator (tools/Caustikon.Glasses.Generator, YamlDotNet) reads the
RefractiveIndex.INFO database (CC0 1.0) and writes both the data of record
(data/glasses/*.json, one provenance record per glass, fit deviations recorded
in manifest.json) and the C# catalog. Nine manufacturers import with closed-form
dispersion: SCHOTT, OHARA, HOYA, CDGM, HIKARI, SUMITA, VITRON, Cargille and
Amorphous Materials; 138 tabulated-only entries are listed as skipped.

Each vendor class exposes the concrete model as a typed field for the hot path
(Schott.NBK7 is a Sellmeier value, no allocation); GlassCatalog resolves by
name with case, spaces and hyphens ignored and boxes once per glass. Glass
carries the printed nd and Vd, glass code, status, density, reference
temperature, tabulated extinction, and SCHOTT-form dn/dT coefficients.
Glass.Define gives a caller's own model the same standing.

TabulatedExtinction turns k(λ) into absorption and internal transmittance for
any path length; ThermalDispersion evaluates the SCHOTT formula for the
absolute index shift; GlassColour integrates transmittance against the CIE
1931 2° observer under D65 into XYZ and sRGB, with gamut clipping reported and
the wavelength coverage of the glass's own data stated.

Tests check every catalogued glass at the exact d, F and C lines against its
printed nd (five units in the fifth decimal plus printed rounding) and Vd
(propagated bound), complete provenance, and name resolution. N-BK7 is pinned
to its SCHOTT datasheet: seven τi rows at 10 mm and 25 mm and nine dn/dT
values across three temperature ranges and three lines, all within the printed
precision. D65 through a perfect transmitter reproduces the D65 white.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
verify.yml now builds and tests both packages on both frameworks, checks the
data of record for provenance and count against the manifest, and packs both
packages with XML documentation. The generator writes LF regardless of host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

levvs and others added 2 commits September 5, 2026 23:55
site/Caustikon.Site is a Blazor WebAssembly application over both packages:
a filterable catalog of every glass, a page per glass with its index curve,
internal transmittance and transmitted colour at a chosen thickness, its
temperature behaviour and its coefficients and provenance, a playground for a
plane interface and a slab, a formulas page naming the implementing types,
and an about page. Charts are SVG drawn from the numbers; the only typeface is
IBM Plex Sans, self-hosted under the OFL.

pages.yml publishes the site to GitHub Pages on pushes to main, rebasing the
document for the project path and copying index.html to 404.html for
client-side routing. release.yml packs and pushes both packages to NuGet.org
on a v* tag when NUGET_API_KEY is present, after checking that the tag matches
the declared version. The README is rewritten around installing the packages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…the page

Only the range controls need the label/value row; the other labels were being
split by the same flex rule. The catalog table lost its horizontal-scroll
wrapper because that wrapper became the virtualization scroll container and
trapped the sticky header inside it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@levvs-one levvs-one changed the title Design/glass catalog Glass catalog, absorption, temperature, colour, and the site Sep 5, 2026
levvs and others added 22 commits September 6, 2026 00:02
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ir row

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The home page traces sixty-one wavelengths through an equilateral prism of a
chosen glass with Dielectric.RefractUnit, draws each ray in its CIE colour and
composites them additively; glass pages and the playground show the visible
spectrum with each wavelength dimmed by the slab's transmittance; the catalog
opens with the Abbe diagram of all 1646 glasses, coloured by manufacturer and
clickable. GlassColour.Monochromatic gives the display colour of a spectral
line from the observer tables, desaturated only as far as the sRGB gamut
requires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…mation

The prism scene now ends on a screen line; each wavelength is marked where it
arrives, so the spectrum's true height is visible, and the readout states it
in millimetres at one metre. Rays glow softly and draw themselves once on
load; reduced-motion users get the finished frame.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
/render traces a sphere of any catalogued glass on a checkered ground at nine
wavelengths with the packages' own RefractUnit, Fresnel and tabulated
absorption: Fresnel-weighted surface reflection into a lit studio
environment, refraction in, up to four internal reflections with Beer–Lambert
loss over every chord, refraction out. Ten commonly used glasses head the
list; the whole catalog follows by manufacturer. The image is pushed to a
canvas band by band so the page stays responsive, and only the tracing is
timed.

Small screens get the bench first, a scrolling nav, full-width controls, a
catalog table reduced to manufacturer, name, nd and νd, and single-column
definition lists. The site is now AOT-compiled for WebAssembly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…o your own code

The renderer now skips the spectral loop for rays that miss the sphere, draws
a quarter-size preview first, renders at 480 px by default, and supersamples
only the pixels whose neighbours disagree. The key light's direction, strength
and the room's brightness are sliders.

/use gives three paths for a chosen glass and thickness: CSS custom properties
and a panel class for interfaces (tint from the transmitted colour, edge and
face from Fresnel, displacement and fringe from the refraction), GLSL with the
glass's own dispersion formula, RGB index and absorption per millimetre and an
exact Fresnel function, and the C# calls. Every number is computed from the
catalog entry; blur is labelled as the design choice it is.

Phones: the document can no longer scroll sideways; tables scroll inside
their own container.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The bench traces the beam through whatever polygon it is given: a regular
polygon with 3–12 corners, a biconvex lens, a tilted plate, or a shape drawn by
clicking on the bench. Rays reflect inside where the exit is past critical and
leave wherever the geometry lets them; the readout reports smallest and largest
deviation, the spread, the size of the spectrum on a screen a metre away, and
how many rays got out.

The readout is now fed by the scene after it has traced, which fixes the
numbers staying at the previous glass's values when the glass changed. The
four figure tiles are gone; the home page says in plain words what was
imported, what was checked and where each page leads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The bench sits next to a panel of its controls with the readout underneath;
corners are dragged with the pointer instead of placed by blind clicks, with
buttons to add, remove and reset them. The render page does the same, and
the solid can now be a sphere, a cube, a prism with 3–12 faces, an
octahedron, a dodecahedron or an icosahedron — all traced as convex solids
through the same refraction, with up to six internal reflections. Five
backdrops are available. The ground pattern has a fixed 16 mm period, so the
size slider changes how the solid sits on it and not only the absorption.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every string the pages show lives in one table with an English and a Russian
form; pages ask for it by key, and inline markup is kept in the strings so
sub- and superscripts survive translation. A menu in the header lists the
languages with a flag and both names; the choice is stored in the browser and
the first visit follows the browser's language. Formulas, code snippets and
glass names stay as they are in both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One glass, one wavelength, one angle, one prism apex, one slab thickness:
index and its derivative, group index, phase velocity, the d/F/C and e/F'/C'
indices with both Abbe numbers and the g–F partial dispersion, refracted
angles both ways, exact Fresnel reflectances, Brewster and critical angles,
path and lateral displacement through a slab with its internal and total
transmittance, and for the prism the minimum deviation and its incidence, the
deviation at the chosen angle, angular dispersion and the F–C spread. Every
value comes from the packages; the notes column says what each one is.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Elements: biconvex, plano-convex, biconcave and meniscus lenses from two
spherical surfaces with adjustable curvatures and thickness, regular polygons
with rotation, a right-angle prism, a tilted plate, and any shape dragged by
its corners; every element takes a size and a height. The beam has an angle,
a height and a ray count, and the view zooms on the element.

Physics: at every face the exact Fresnel split sends part of each ray out and
keeps part inside, so rays fade with their energy and ghost beams appear;
absorption over each chord uses the glass's k table at a chosen millimetre
scale; the glass temperature shifts its index through its own dn/dT; the
surrounding medium can be vacuum, air, helium, CO2, water, ethanol, glycerol,
benzene, immersion oil or carbon disulfide, with catalog indices converted
to absolute first. Hovering a ray shows its wavelength, index, deviation and
energy; the readout adds energy out, reflected at entry and absorbed.
Controls sit in compact groups beside the bench, with a 10 mm scale bar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Home bench fills the width; controls sit under it in a fluid grid with no panel, group headings or grey text.
- Ctrl+wheel zooms about the cursor (0.25-40x), dragging empty space pans, double click resets.
- Draw your own outline click by click; lens outlines are decimated to 12 handles when edited; removing a corner
  drops the least important one; a self-intersecting outline is flagged and drawn dashed.
- Size and height now apply to custom shapes; wider ranges on every slider; n_d at temperature in the readout.
- Render page traces on the GPU: a WebGL2 fragment shader with the same nine wavelengths, Fresnel split,
  six bounces and Beer-Lambert absorption; drag to orbit, Ctrl+wheel to dolly; CPU path kept as fallback.
- English is the default language until a visitor picks one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… you can type, RU decimals

- Navigation is Catalog, Design, 3D, Optic and a Give Me! menu with one page per craft: design, games,
  3D and Blender, web, .NET. Each page: what the physics asks for, a table of six glasses computed from the
  catalog, advice, worked examples and code (HLSL/GLSL, Blender node values, three.js and glTF, C#, CSS).
  GitHub is a mark in the header; the footer links the author.
- Design page traces a glass panel over an interface in a WebGL2 shader: bevel and dome refraction per channel,
  Fresnel sheen from the room, tint from the k table, frost kept separate; the shader ships with the glass baked in.
- Every slider has a number box; secondary settings fold under More settings.
- Numbers use a comma decimal in Russian everywhere except code; middle-dot separators are gone.
- 3D render accumulates up to 64 jittered samples when still, dollies toward the cursor, and the ground pattern is
  offset half a tile so a tile edge no longer sits under the solid's centre.
- Meta descriptions, Open Graph, JSON-LD, robots.txt and sitemap.xml.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…o render, exclusive menus

- Give Me! pages keep the site's own look (underline sub-navigation, no pills) and become tools: pick a glass and
  a thickness, then format tabs write the exact numbers: CSS, Tailwind, Figma, GLSL; Unity HDRP, Unreal, Godot 4,
  HLSL/GLSL; Blender node values (Volume Absorption density and colour reproduce alpha exactly), glTF, USD;
  three.js; four C# snippets. Every parameter is explained with its origin; examples use the chosen glass.
- Glass page: where to take the glass (Design, 3D, Optic, Give Me! with the glass preselected), derived numbers
  (n_e, nu_e, P_gF, dn/dlambda, group index, Brewster, critical, R0, R60, n and alpha per channel, 20/nu_d,
  against N-BK7), daylight strips at seven thicknesses, Fresnel-against-angle charts both ways.
- 3D render: studio environment with softboxes and a fill, contact shadow under the solid, ACES tone curve and an
  exposure control; the CPU fallback matches.
- Design page: shape (rectangle, pill, circle), what lies behind the glass, lamp strength, side-by-side comparison
  with another glass, PNG export, code in tabs, glass preselected from the address.
- Header menus close one another and close on a click outside; footer laid out in two rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nder convergence

- The texts that explained the project (what it is, where things are, install, use, data, checks, limits,
  citation, author) move from the Optic page to an About tab after Give Me!; Optic keeps the bench and calculator.
- Phones: readout in three columns, smaller figures and hints, canvases at one device pixel per CSS pixel.
- Abbe diagram uses one click handler for the whole chart instead of one per glass.
- 3D: each still frame takes four jittered taps, so 64 samples arrive in 16 frames; the checker is less harsh
  so the inside of a solid reads as glass rather than a tangle.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…flash, no black holes in the render

- Phones: the nav no longer scrolls sideways, so the Give Me! list is not clipped; tap highlight removed.
- Bench: two fingers pinch to zoom about their midpoint and pan; one finger pans or drags a corner; pointer capture
  keeps a finger's moves after it slides off the element.
- 3D: two fingers dolly; twelve internal bounces and whatever light is still trapped leaves along the last exit
  instead of turning black.
- Design: the outline and the bevel's inner border blend over a pixel; defaults show the bend (10 mm at 8 px/mm,
  40 px bevel, dome 0.4, no frost).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…olyhedron

- A photon pass traces a jittered grid of lamp photons at three wavelengths through the solid onto the table and
  accumulates them into a map; the table's lamp light comes from that map, so the solid casts its shadow and focuses
  its caustic, with colour fringes where the glass disperses. The room's share keeps a light contact shade.
- Every polyhedron gets a narrow flat along each edge (faces sharing two vertices), so edges catch highlights and
  the solids stop reading as mathematically sharp. Plane arrays grow to 64.
- The CPU fallback keeps the chamfers and an even lamp on the table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Nine wavelengths per sample take a random offset inside their bands from a 33-point table, so colour speckle on
  dispersing edges averages into a continuous spectrum; while turning, three bands at band centres.
- Two taps per still frame over 24 frames, photons 288x288x3 over 8 frames with 8 bounces, backing store capped at
  1.5 device pixels per CSS pixel and 1400 px wide.
- A brighter, softer studio: higher zenith, broader softboxes, lighter dark tiles, so internal reflections no longer
  fall into black.
- Camera starts farther back; + and − buttons over the stage step the distance.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… black; Give pages lose the topic strip

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
levvs and others added 4 commits September 6, 2026 18:17
- Water (Daimon and Masumura 2007 fit; Hale and Querry 1973 k), ethanol, methanol, acetone, glycerol, ethylene
  glycol, benzene, toluene and carbon disulfide join the catalog as the Liquids vendor.
- The generator reads a curated list of formula and k files, accepts tabulated nk tables, and writes the fit's own
  nd and Vd into the catalog fields when no datasheet value exists, saying so in the provenance notes.
- Tests pin water's index, its blue over ten metres and its colourlessness over a centimetre.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e pictures match the site

- tools/Caustikon.Gallery renders four solids with the site's own tracer and writes PNGs into docs/gallery.
- The CPU tracer now builds the same lamp photon map as the GPU (shadow and caustic), renders rectangular frames,
  and the table light is rebalanced on both paths so open tiles no longer wash to white.
- README: badges, the gallery, what each page of the site does, the liquids.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Wang's k table for glycerol starts at 1200 nm; clamping to its edge gave 98/m in every visible channel and painted the liquid black. The entry keeps Gupta's index fit and no extinction, like the other liquids without a visible k measurement.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The solid's surroundings were a bare gradient with nothing to refract, so
the lower half of a sphere, which shows what stands behind and below, read
as broken. A forest backdrop, now the default: a panorama of seventy-two
spruces on the ground round the solid, traced once by direction (in
millimetres, scaled to the solid's units, lit by the same sun and sky),
looked up wherever a ray leaves the scene; the near floor is lit as the table
with the photon map, the far floor is the panorama's.

Two faults in the photon map came out with it: the emitter was centred over
the solid, not the table, so the beam landed shifted by the lamp's slant and
left the map's corner nearest the lamp unlit, and the map was a 32-bit float
texture filtered linearly, which without OES_texture_float_linear is
incomplete and reads as zero, putting the whole table in shadow on such GPUs.
Now the emitter starts above the table's centre, is wide enough for the
corners at any azimuth, and the map is sampled nearest with four taps.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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