mathematics – Emulate doom-style raycaster projection distortion with modern graphics apis

Currently working on a doom-like engine with fewer technical limitations, and looking into rendering techniques. I’m aware doom’s a raycaster, and I want to capture a similar look but with modern graphics APIs, without implementing a raycasted column-renderer in them.

One of the technical limitations I’m ignoring is on the inclination of the camera, which was locked to be parallel in doom due to the “column” drawing. Modern faithful sourceports, such as crispydoom, and some of the later-era doom-based games like Heretic, allowed looking up-and-down using y-shearing. In the image bellow, taken from the linked page, the green rectangle represent the regular un-inclinded view and the red rectangle represents the “inclined” view.

image from linked page, displaying y shearing animated view of y-sheared camera

From the image, you can see that it’s effectively rendering a vertically wide FOV, and cropping it – though with column rendering that’s a little more direct. This is different from simply adjusting the height of the camera, as with this method the vanishing points remain at their original location – causing some distortion as you look up and down. For example in the image above the apparent angle between the columns and roof don’t change with this method, where-as with moving the camera upwards you would expect the angle between them to become more orthogonal the closer they come to the vertical-center of the camera’s view.

I would like to emulate such a distortion using modern graphics APIs (wgpu, vulkan, dx12, metal) without implementing the equivalent of the software renderer, and without overdrawing the screen and then cropping. I’m also definitely only looking for an approximate emulation of the effect, if it looks pretty close then that’s good enough

I did also see this on one of the other exchanges, and it sounds eerily similar to how I described y-shearing:

I imagine that you would cancel out the inclination of the camera in the view matrix, then somehow map it to a vertical “shift” of the projection matrix, though I’m uncertain how to perform that mapping – or if there even is a sensical one.

Thanks for your time!