Note: In order to keep the question as simple as possible, I am actively changing the body of the question to reflect the current state of affairs, instead of adding stuff at the bottom.
I am implementing interface rotation for my GLES based game for iOS, written in Xamarin.iOS with OpenTK.
I am detecting the rotation by overriding
WillRotate, in my
UIViewController, and I correctly re-setup all of my projection matrices.
However, the results of drawing a sprite on landscape and portrait modes are slightly different -landscape is a bit blurry-.
This is the test sprite I am using, which is 128x128 to avoid any rounding errors:
My test projection matrix is based on a 1024x768 display for an iPad. Even though I won't be scaling the image, I am using point filtering, so I expect rendering to be pixel perfect. The rendering position is (0, 0) once again to avoid any rounding errors. The sprite should fall exactly into the pixel boundaries for both portrait and landscape.
Additionally, in both cases, I'm using the same texture with the same sampler, the same shader, and the same GL state.
This is what happens when I render the sprite in portrait mode. This is pretty much how I expect it to be rendered (magnified 5x):
And this is what happens when I render the same sprite in landscape mode.
My belief is that the framebuffer was created as 768x1024, but when rotated, it is made to fit the 1024x768 screen, squished on the horizontal and stretched in the vertical, and this is what is causing the problem.
If I set OpenTK to create a 1024x1024 framebuffer, the result becomes consistent in portrait and landscape. This is portrait:
Notice how there is be no distortion on the vertical, which happens to be 1024 pixels as well. The distortion is limited to the horizontal, where the resolution doesn't match. This is landscape:
This time the distortion moved to the vertical, supporting my hypothesis.
Furthermore, creating it at 3072x3072, 3072 being the least common multiple of 1024 and 768, the results are correct both in portrait and landscape:
Notice that this is not a solution, since not only I'm wasting a lot of memory, but also will create inconsistent multisampling artifacts with 3D, as the vertical scaling is different from the horizontal scaling. Additionally, this is not an option for the iPhone 5, whose resolution of 1136x640 would require me to create a framebuffer of 45440x45440.
Since a device rotation could be thought of as a window resize, I think that the framebuffer has to be recreated to match the new size. This is necessary for Windows on Direct3D. I would have to call
swapChain.ResizeBuffers() to do this in SharpDX.
I have tried setting
AutoResize = true in my
iPhoneOSGameView, but then the framebuffer gets clipped as I rotate the interface, and then everything disappears when rotating the interface again.
I'm not doing anything strange, my framebuffer initialization is pretty vanilla:
int scaling = (int)UIScreen.MainScreen.Scale; DeviceWidth = (int)UIScreen.MainScreen.Bounds.Width * scaling; DeviceHeight = (int)UIScreen.MainScreen.Bounds.Height * scaling; Size = new System.Drawing.Size((int)(DeviceWidth), (int)(DeviceHeight)); Bounds = new System.Drawing.RectangleF(0, 0, DeviceWidth, DeviceHeight); Frame = new System.Drawing.RectangleF(0, 0, DeviceWidth, DeviceHeight); ContextRenderingApi = EAGLRenderingAPI.OpenGLES2; AutoResize = true; LayerRetainsBacking = true; LayerColorFormat = EAGLColorFormat.RGBA8;
I get inconsistent results when changing
Frame on my
CreateFrameBuffer override. Unfortunately, the documentation is very incomplete, so I have resorted to randomly changing stuff here and there without really knowing what is going on.
There is a similar question which has no answers. However, I don't know if they're experiencing the same problem as I am.
Also, there is a similar concern over at the xamarin forums, specifically mentioning the rotation issue. There seems to be no solution outside of dropping
Is my supposition that recreating the framebuffer is necessary, correct? If so, does anybody know how to do it correctly in OpenTK for Xamarin.iOS?