Skip to content

feat: add Ray Tracing simulation - #395

Merged
mattqdev merged 1 commit into
physicshub:mainfrom
charlenenicer:feat/ray-tracing-simulation
Sep 25, 2026
Merged

mattqdev merged 1 commit into
physicshub:mainfrom
charlenenicer:feat/ray-tracing-simulation

Conversation

@charlenenicer

@charlenenicer charlenenicer commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Adds a new Ray Tracing simulation (optics, University level) plus a theory article.

A real Whitted-style ray tracer renders a sphere on a checkered floor lit by a point light. The learner follows one ray at a time: click any pixel and every step the renderer took to colour it is shown with its live numbers:

  1. Primary ray: $\vec P(t) = \vec O + t\hat D$ through the chosen pixel
  2. Ray–sphere intersection: the quadratic $at^2 + bt + c = 0$ and its discriminant $\Delta$ (miss / graze / hit), plus the ground plane $t = -O_y/D_y$
  3. Inverse-square law: $E = I_0/d^2$
  4. Shadow ray: blocked if something lies between the hit point and the light
  5. Lambert's cosine law $I_d = k_d E \max(0, \hat N\cdot\hat L)$ and the Phong highlight
  6. Law of reflection: $\hat D_r = \hat D - 2(\hat D\cdot\hat N)\hat N$, traced recursively

The ray-traced image and a side/top diagram of the scene sit side by side. The camera, sphere and light can be dragged in the diagram (the sliders follow), and the diagram draws the followed ray with its normal, shadow ray (red when blocked) and reflected ray. Below the image, the equations are written out with the numbers substituted. Each line glows briefly when its value changes, so it's easy to see, for example, that moving the light leaves the ray, the intersection and the reflection angle untouched.

Files

File What
simulations/RayTracing.jsx The simulation. There are no forces, so like TrigonometricCircle it draws in pixel space from draw. The image is cached and re-traced progressively, only when the scene changes: a 1/4-resolution preview right away, then a 2×2 anti-aliased pass spread over a few frames once the scene has been still for 150 ms. This keeps dragging smooth. Every input is guarded in sceneFrom, since slider bounds no longer limit typed values.
app/(core)/data/configs/RayTracing.js Camera / sphere / light / material controls (SI: m, °, W/sr) and the SimInfoMapper readout.
app/(core)/data/chapters.js Catalogue entry #17: level: "undergraduate", alsoFor: ["upperSecondary"], difficulty: "core", tags Optics / Vectors / Interactive.
app/(core)/data/simulationOverviews.js Overview: intro, controls, concepts, KaTeX formulas.
app/(core)/data/articles/how-does-ray-tracing-work.js New article "How does ray tracing work?", written to the new-article house style (key fact, takeaways, FAQ, "Keep exploring"). It is the sim's relatedBlogSlug, so it shows first under "Recommended reading", with the sim thumbnail as its card image.
app/(core)/data/curriculumTopics.js New ray-tracing concept, placed at undergraduate level in all six curricula with the senior-physics stage as also (same pattern as three-body / pi-collisions), plus sim:RayTracing and blog:how-does-ray-tracing-work rows.
public/thumbnails/ray-tracing.webp Thumbnail (1200×675).
app/(core)/engine/runtime/createSimulation.jsx Engine change: see below.
CLAUDE.md, .claude/skills/new-simulation/SKILL.md Document setInput and the new precedent, as required for engine changes.
routes.js, public/sitemap.xml, public/feed.xml, public/llms*.txt Regenerated by npm run build.

Engine change: setInput(name, value)

Dragging an object in the diagram is a parameter change, so the sliders must follow. The runtime had no way for a sketch to write an input back, so createSimulation now exposes setInput(name, value) in the build context and every hook context. It updates inputsRef synchronously, so the next frame already reads the new value through inputs, then goes through the same handleInputChange path as the sliders. The change is additive, and no existing simulation is affected. The skill documents that it's for canvas gestures that are parameter changes, not for storing simulation state.


✅ Checklist

  • Verified that the project builds and runs locally (npm run dev, npm run build: 56/56 pages generated, rebased on the latest main)
  • Ensured no ESLint or TypeScript warnings/errors remain (npx eslint . clean; prettier --check is clean on every file this PR touches, see notes)
  • Updated documentation, comments, or in-code explanations where needed (CLAUDE.md, new-simulation skill, derivations in comments)
  • Verified responsiveness across devices (desktop 1440px, tablet 820px, phone 390px: no horizontal overflow; the canvas switches from side-by-side to stacked)
  • Followed the CONTRIBUTING.md guidelines

🎨 Visual Changes (if UI-related)

ray-tracing-demo.mp4

Clip (20 s): the light is dragged behind the sphere and a floor pixel inside the shadow is followed (shadow ray turns red, $I_d = 0$). Then the sphere is moved, and the diagram switches to the top view while the camera swings around.


📂 Type of Change

  • New feature (non-breaking change that adds functionality)
  • Documentation update

Additional Notes for Reviewers

  • Physics checks. $E = I_0/d^2$ was checked against the readout (22 W/sr at d = 8.45 m → 0.308 W/m²). $\Delta < 0$ switches the hit to the floor. A floor point in the geometric shadow reports a blocked shadow ray with $s < d$. The reflection angle stays constant while only the light moves.
  • Brightness model. E is used directly as exposure (1 W/m² on a white matte surface facing the light is full white). Linear light is clamped and gamma-encoded ($x^{1/2.2}$). The Phong highlight is noted as empirical in both a code comment and the article.
  • Performance. A full trace per frame is far too slow for 60 fps, hence the cached progressive render. The per-frame budget for the sharp pass is a rendering time budget, not physics time: no simulation state depends on it.
  • Out-of-range inputs. Tested via URL with fov=180&shininess=-5&radius=0&reflectivity=3&intensity=-10&camY=-2: no NaN/Infinity in any readout and no errors.
  • Lockfile / formatting on main. package-lock.json on main is currently out of sync with package.json (the @supabase/* packages and semantic-release are missing, so npm ci fails). I installed with --no-package-lock and did not touch the lockfile. prettier --check . flags .claude/skills/new-article/SKILL.md, app/(core)/lib/community.ts and release.config.js on main itself; I left those alone to keep the PR focused.
  • Phone layout. On narrow screens the shared sim-info panel docks at the bottom of the canvas and covers the live-equations box until it is collapsed. This is the same behaviour as the other simulations, so I left the shared panel alone.

Add an interactive Whitted-style ray tracer that follows one ray of light
from the camera into a 3D scene (sphere, ground plane, point light):

- simulations/RayTracing.jsx: ray-traced image and a draggable side/top
  diagram side by side, with the followed ray's normal, shadow ray and
  reflected ray, plus live equations with the numbers substituted. The
  image is cached and re-traced progressively (quick preview, then an
  anti-aliased pass) only when the scene changes. Every input is guarded
  so typed values outside the slider ranges stay stable.
- configs/RayTracing.js: camera/sphere/light/material controls and the
  sim-info readout.
- chapters.js entry (undergraduate, also upper secondary), thumbnail,
  simulationOverviews entry, and a "ray-tracing" concept in
  curriculumTopics.js for the simulation and its article.
- New article "How does ray tracing work?" linked as relatedBlogSlug.
- createSimulation: expose setInput(name, value) in the hook context so
  dragging on the canvas can move sliders; documented in CLAUDE.md and
  the new-simulation skill.
- Regenerated sitemap, routes, feed and llms files.

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

vercel Bot commented Sep 25, 2026

Copy link
Copy Markdown

@charlenenicer is attempting to deploy a commit to the PhysicsHub's projects Team on Vercel.

A member of the Team first needs to authorize it.

@mattqdev

Copy link
Copy Markdown
Collaborator

Hey @charlenenicer Thank you so much for this simulation! Really appreciate this

@mattqdev
mattqdev merged commit 6696422 into physicshub:main Sep 25, 2026
1 of 2 checks passed
@physicshub

Copy link
Copy Markdown
Owner

🎉 This PR is included in version 3.35.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants