Reputation: 29
How can I adjusted projection of my project onto a curved surface without distortion of the image?
I have been building a Virtual Reality game that will be projected onto a curved screen, which is roughly the shape of a half-moon shape. My game now works nicely when I run it on a flat screen. However, when I connect my computer to my laser projector (DLP3010 Texas Instruments projector), and project onto some rear projection material set up in a half-moon shape, the objects that are located in the side most parts of the field of view in the game become distorted/stretched.
Flat screen:
Curved screen:
I have tried adjusting the FOV of the Camera3D as well as other properties, I have tried using a subviewport based on asking ChatGPT, but I have not had any success so far with rendering the projection in a way to avoids the distortion of the more ‘peripheral’ objects in the field of view. If you have any suggestions I could follow, I would greatly appreciate it. My project is available on GitHub, if cloning the repo and importing it to Godot (I'm using the 4.3 .NET version), it should work.
Upvotes: 2
Views: 108
Reputation: 31
This is a fundamental issue with the way 3D scenes are commonly rendered. Parts of the image that are further away from the focal center of the camera are increasingly distorted, stretched radially away from the center. This inherent distortion is fine with flat screens because the mathematical model used to create the image assumes that the scene is projected onto a flat plane.
When dealing with non-flat screens, you need to counteract this distortion with an opposite distortion: Barrel Distortion
Barrel distortion essentially expands the area near the center of the image OR shrinks the area at the edge of the image. Either way, it stretches the image in a radially symmetrical fashion, in the opposite way that perspective projections introduce distortion. You can read more about barrel distortion here: https://www.decarpentier.nl/lens-distortion
Barrel distortion can be implemented in one of two ways: Either as a post-processing shader or as a vertex shader applied to every mesh.
The vertex shader approach is expensive to compute and not used by anything I know of, so I can't help you with it. However, it would allow you to virtually extend the camera FOV to more than 180°, which could be interesting for you.
The post-processing shader approach is relatively cheap to compute, but will either introduce a black curved (or even circular) border around the screen. This is solved by scaling up the image, but causes the center of the image to be blurry. This last problem is fixed by rendering at a larger resolution.
Here is an implementation of barrel distortion for Godot: https://godotshaders.com/shader/2d-radial-distortion-fisheye-barrel/ This specific implementation only shrinks the image inwards, leaving a black circle around the edge of the screen. You probably want to scale the image up to remove that. The aforementioned blog post includes a lot of math and shader code, so you can always refer to that when making modifications to the shader.
A last thing to mention is that your setup in particular features a very wide screen, so it might be better to only apply the distortion along the Y-axis to reduce the performance impact, but I will leave that for you to experiment with.
Asides:
The only game I can think of that allows you to play with barrel distortion is Teardown. People generally dislike it, and understandably so, considering most people are playing on flat screens and are used to the edge distortions anyway.
When the Oculus Rift was being sold in 2014, every video and livestream showed both the left and right eye images. This was difficult to look at, but revealed an interesting detail: Each image is shrunk down with barrel distortion! The distortion was applied at about 50% strength, so the outer edge of the screen wasn't a circle.
Upvotes: 1