Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding retina display support results in OpenGL ES not drawing anything

I have an app that draws a scene in OpenGL ES 2.0. Everything renders correctly in the iPhone and iPad simulators, as well as on real devices, so long as I don't attempt to make use of the retina display. Retina devices still draw, but with the same resolution as older devices.

On new devices, I get only a black screen. On the retina simulators, I get a pink screen. The program won't even make use of the value I set with glClearColor();

I can correctly set the scale factor for the device with the following code:

_eaglLayer = (CAEAGLLayer *)self.layer;
_eaglLayer.opaque = YES;

self.contentScaleFactor = [[UIScreen mainScreen] scale];
_eaglLayer.contentsScale = [[UIScreen mainScreen] scale];

And I can correctly create a render buffer here:

glGenRenderbuffers(1, &_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.frame.size.width, self.frame.size.height);
//Context is an instance of EAGLContext
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];

I set the size of the viewport as follows:

glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);

...

glViewport(0, 0, _backingWidth, _backingHeight);

All of this code works on older devices, and it works flawlessly if I comment out the lines:

self.contentScaleFactor = [[UIScreen mainScreen] scale];
_eaglLayer.contentsScale = [[UIScreen mainScreen] scale];

I've logged the scale as the view loads, and it correctly sets the value to 2.0 on retina devices or 1.0 on older devices.

I've tried a number of different solutions and methods of setting the scale factor, but to no avail. I know there's something I'm just not seeing, but I can't find it. Suggestions?

like image 827
bindsniper001 Avatar asked Jan 14 '23 00:01

bindsniper001


2 Answers

Somebody else mentioned that the call to eaglLayer.contentsScale isn't necessary, but for some reason this only works when I do call it. I'm using the following code in a UIView subclass, and rendering works beautifully on all devices:

CGFloat scale = [[UIScreen mainScreen] scale];

_eaglLayer.contentsScale = scale;
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];

CGSize s = self.frame.size;
glViewport(0, 0, s.width * scale, s.height * scale);
like image 165
Bradley Snyder Avatar answered Jan 19 '23 00:01

Bradley Snyder


I was facing the same problem. The call to eaglLayer.contentsScale = [[UIScreen mainScreen] scale]; is not needed and you have to multiply the frame dimensions with the screen scale. So the solution for your problem would be:

CGFloat screenScale = [UIScreen mainScreen].scale;
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, CGRectGetWidth(self.bounds) * screenScale, CGRectGetHeight(self.bounds) * screenScale);
like image 33
Quxflux Avatar answered Jan 19 '23 00:01

Quxflux