Double inverted y axis caused confusion, and a stubborn bug in the triangle intersection code that I only found after looking over the code 4 times — some plus should have been a minus!
But now adding a rectangle object is trivial (screenshot uses multisampling with 10 samples)