
Indirect3D
Indirect3D is a completely ridiculous attempt to implement a significant portion of the DirectX / Direct3D API using a HTML canvas's 2d context. That means doing all the math in JS.
I started this project at least 10 years ago. It's based on DX9, which came out in 2002—but it's not quite that old.
In 2021, for no especially clear reason, I started working on it again. A rough changelog is below.
In modern browsers in 2021, it actually runs fairly quickly. As long as it's not trying to do much.
To start or stop some random animation, hit Enter.
In the scene above, the red and blue triangle have the same vertex model coordinates and same xy translation with offset z depth. You can control that with the red and blue depth controls above.
Try WASD and QE 😉.
Finally you can mess with the field of view angle if you want. I don't know what normal cameras are.
The pretty rainbow triangle moves back and forth along the world z-axis, while a colorful little pyramid sits stoically.
Changelog
- August 2021
- Convert to TypeScript. Add webpack and TS configs.
- Organize into more, smaller files.
- Fix bug transposing g and b color channels in triangle list.
- Refactor and clean-up LINELIST and LINESTRIP modes to share common functionality.
- Implement barycentric coordinate calculation for triangle color blending.
- Calculate triangle color blending in CIELAB space rather than sRGB space.
- Fix row-major/column-major disconnect and transpose transformation matrices.
- Fix triangle z-depth calculation by projecting a ray from the screen back to the plane of the triangle.
- Adding that gave me backface culling for free, score!
- Fix alpha blending, which was confused about background/foreground.
- Added keyboard controls, hahahaha.
- Fixed TRIANGLELIST and TRIANGLESTRIP modes and added TRIANGLEFAN.
- Switched triangle color calculation from screen space to view space and I think it's a little more stable?
- Added lighting.
- December 2022
- Implement DrawIndexedPrimitive, SetStreamSource, and SetIndices.
- Implement directional lights and LightEnable.
Known issues and ToDos
- Line color blending is still done in sRGB space. Will probably look better in CIELAB.
- There's a lot of packing and unpacking RGBA values into Int32 and it's sometimes error prone. Is it necessary? Could
Color
be a struct (or a few structs for different color spaces)? - The aliasing, oh god the aliasing!
- So... depth is hard.
Things that work pretty well
- Barycentric coordinates work great for triangle coloring. (Even if they're in the wrong coordinate system.)
- sRGB—XYZ—CIELAB color space conversion, and doing the color blending in CIELAB, looks real nice.
- Alpha blending is now working correctly!
- Backface culling was fairly straightforward.