A high-performance, zero-installation 2D optics simulator powered by Rust, WebAssembly & TypeScript.
Live Demo | Features | Architecture | Challenges | Getting Started | Roadmap
A virtual optics lab that runs entirely in the browser — near-native performance on any device, including low-end student laptops and tablets.
- Real-time Ray Tracing — Physically accurate ray paths computed at 60fps via a compiled Rust engine
- Snell's Law & Dispersion — Wavelength-dependent refractive indices using the Cauchy equation
- Total Internal Reflection — Automatically detected and rendered when critical angle is exceeded
- 7 Optical Elements — Plane mirror, convex/concave lens, convex/concave mirror, glass block, prism
- 3 Light Source Types — Single ray, parallel beam, point source with adjustable cone angle
- Material Library — Air, Water, Crown Glass, Flint Glass, Diamond, Acrylic, Ice — swap instantly
- Wavelength Slider — Adjust from 400nm (violet) to 700nm (red) with live chromatic dispersion
- Interactive Protractors — Draggable measurement tools that auto-snap to surfaces and display incidence/refraction angles
- Dark Mode + Neon Glow — Dark grid with glowing ray paths for crystal-clear beam visualization
- Snap-to-Grid — Precision alignment for setting up experiments
- 7 Challenge Modules — Gamified scenarios from Easy to Expert difficulty
- Zero Installation — Runs entirely in the browser, ~100KB total bundle
The system is organized into three clean layers:
┌──────────────────────────────────────────────────┐
│ Frontend (TypeScript + Canvas) │
│ UI · State Management · Rendering │
├──────────────────────────────────────────────────┤
│ Bridge (WebAssembly) │
│ Near-native in-browser execution │
├──────────────────────────────────────────────────┤
│ Physics Engine (Rust) │
│ Ray tracing · Collisions · Snell's Law │
└──────────────────────────────────────────────────┘
| Layer | Technology | Size |
|---|---|---|
| Physics Engine | Rust | ~64 KB WASM |
| Browser Bridge | WebAssembly (wasm-bindgen) |
— |
| Frontend | TypeScript + HTML5 Canvas | ~31 KB JS |
| Build Tooling | wasm-pack + Vite |
— |
The core computational layer handles all intensive math, vector geometry, and physics logic:
- Ray generation — Single rays, parallel beams, and point sources with configurable parameters
- Collision detection — Vector–boundary intersections in 2D with epsilon tolerance
- Reflection — Surface normal-based reflection angle calculation
- Refraction — Full Snell's Law implementation with Cauchy dispersion model
- Ray culling — Dynamic termination for rays exiting the viewport, reducing CPU overhead
- Material system — Wavelength-dependent refractive indices:
n(λ) = A + B/λ² + C/λ⁴
- GPU-friendly Canvas 2D rendering with glow effects
- Responsive pan/zoom camera system
- Drag-and-drop element placement with grid snapping
- Keyboard shortcuts for rotation, deletion, direction setting
| Tool | Description |
|---|---|
| Material Library | Dropdown to swap the medium of optical components (Crown Glass, Water, Diamond, etc.). Instantly updates the refractive index and recalculates all ray paths. |
| Interactive Protractors | Draggable measurement tools that auto-snap to the normal line of any optical surface, enabling precise measurement of incidence, reflection, and refraction angles. |
| Wavelength Controller | Slider to adjust light source wavelength (400 nm – 700 nm). The engine recalculates subtle refractive index variations, visually demonstrating chromatic dispersion. |
Gamified scenarios that test theoretical understanding through hands-on application:
| # | Challenge | Difficulty | Goal |
|---|---|---|---|
| 1 | Mirror Bounce | Easy |
Redirect a laser to hit a target using two plane mirrors |
| 2 | Focus the Beam | Easy |
Focus a parallel beam to a point using a convex lens |
| 3 | Rainbow Maker | Medium |
Create visible dispersion through a prism |
| 4 | Total Internal Reflection | Medium |
Bounce light twice inside a glass block |
| 5 | Build a Periscope | Hard |
Construct a periscope with two 45° mirrors |
| 6 | Lens & Mirror Combo | Hard |
Hit a target using one convex lens and two mirrors |
| 7 | Fiber Optic Cable | Expert |
Guide light through 4 glass blocks via total internal reflection |
| Key | Action |
|---|---|
R / Shift+R |
Rotate selected element (15° steps) |
D |
Set direction for selected light source (click to aim) |
Delete / Backspace |
Remove selected object |
Escape |
Deselect / cancel tool |
Scroll |
Zoom in / out |
Right-click drag |
Pan the canvas |
# 1. Clone the repository
git clone https://github.com/hasnain7abbas/optics.git
cd optics
# 2. Build the WASM physics engine
wasm-pack build --target web --out-dir web/pkg
# 3. Install frontend dependencies
cd web
npm install
# 4. Start the dev server
npm run devOpen http://localhost:5173 in your browser.
cd web
npm run build # builds WASM + frontend
npm run preview # preview the production build| Layer | Technology |
|---|---|
| Physics Engine | Rust |
| Browser Bridge | WebAssembly (WASM) via wasm-pack + wasm-bindgen |
| Frontend | TypeScript, HTML5 Canvas |
| Build Tooling | Vite, vasm-pack |
| Serialization | serde + serde-wasm-bindgen |
optics/
├── src/ # Rust physics engine
│ ├── lib.rs # WASM bridge & Simulation API
│ ├── vec2.rs # 2D vector math
│ ├── material.rs # Material library & Cauchy equation
│ ├── optics.rs # Optical elements, light sources, geometry
│ └── tracer.rs # Ray tracer core
├── web/ # TypeScript frontend
│ ├── src/
│ │ ├── main.ts # App entry, event handling, state
│ │ ├── renderer.ts # Canvas rendering, wavelength→color
│ │ ├── challenges.ts # Challenge module definitions
│ │ ├── types.ts # TypeScript type definitions
│ │ └── styles.css # Dark mode UI styles
│ ├── public/
│ │ └── favicon.svg # App icon
│ ├── index.html # Entry HTML
│ ├── package.json
│ ├── tsconfig.json
│ └── vite.config.ts
├── Cargo.toml
├── logo.svg
└── README.md
- Core ray tracing engine (reflection, refraction, TIR)
- Material library with wavelength-dependent refractive indices
- 7 optical elements (mirrors, lenses, glass block, prism)
- 3 light source types (ray, beam, point source)
- Interactive protractors with auto-snap
- 7 challenge modules (Easy → Expert)
- Dark mode with neon glow rendering
- Snap-to-grid alignment
- Data export pipeline (CSV: intersection coords, angles, intensity)
- Hardware-in-the-loop integration (Web Serial API)
- Curved surface rendering for concave/convex mirrors
- Multi-wavelength white light simulation
- Save/load experiment configurations
- Mobile touch support
Bridge the browser application to external microcontrollers via the Web Serial API, enabling the simulator to interface directly with physical sensors on a real-world optical bench.
Export raw intersection coordinates, refraction angles, and intensity data to CSV for advanced analysis and lab report generation.
Contributions are welcome! Feel free to open issues or submit pull requests.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Built with Rust + WebAssembly for the browser.
Made by Hasnain Abbas