I’ve been building a vanilla 3D object to SVG renderer in Typescript to help render circuit boards that are made in React and discovered an interesting trick to keep the SVGs small while getting approximately-correct looking perspective transformations with image textures.An example circuit board rendered with our vanilla Typescript 3D Renderer. Great for checking sizing! You can see we were able to project the “texture” containing the PCB traces!SVGs don’t support perspective transforms like CSS (or at least they’re not guaranteed to work in image viewers), so we need a way to simulate this perspective transformation without creating a massive SVG. It’s easy to draw the box below, you can just project the face of each side of the cube into a polygon, but mapping the texture to that perspective transform isn’t natively possible!Perspective transforms in CSS using the transform attribute (from MDN)So SVGs don’t support perspective transforms, what do they support? SVGs support this nice little transform called an affine transform. This 6 number transform is what you get when you do transform: matrix(a,b,c,d,e,f) in CSS. They are super useful for 2D transformations, like panning/scaling/dragging, but can’t really project into 3d.This projection isn’t possible with a single affine transform. You also can’t combine affine transformation matrices together to create this shape.How can we approximate the transform? Here are some ideas I mulled over that could achieve a good result:Redraw the image with the distortion. This is potentially expensive and means that we can’t use SVGs as the images without converting them to bitmaps. It also means that things might look “fuzzy”Ray trace everything! By projecting a ray to compute each pixel for the image, I could get a very conventional 3d renderer. This doesn’t achieve my goal of lightweight SVGs thoughSubdivide the image and project each subdivision in the most locally-correct affine transformation. Use projected polygon clip ...
First seen: 2025-06-05 02:48
Last seen: 2025-06-05 22:03