2

I have a UIView that I would like to map onto a face of my shape. All that works but I would like it to work with retina graphics on iPhone 5. I set my openGL layer's contentScale property to 2.0 but nevertheless, the result is slightly blurry. So the size is right, it just seems as if I were using non-retina graphics for an image on the retina display. So the 'only' thing I have to do is to tell the iPhone that this has to be double the pixels. I tried the solution DarthMike suggested, unfortunately to no avail.

Here I initialize and add it to my view:

    MyOpenGLView *view = [[MyOpenGLView alloc] initWithFrame:CGRectMake(0, dY, 230,230) context:context];
    view.contentScaleFactor = 2.0;
    view.layer.contentsScale = 2.0;
    view.delegate = view;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    [view setupGL];
    [self.view addSubview:view];

Here I render the view into a context and add it as a texture

    MyViewToBeTheTexture *textureView = [[MyViewToBeTheTexture alloc]initWithFrame:CGRectMake(0, 0, 230, 230)];

    self.effect.texture2d0.enabled = true;

    // make space for an RGBA image of the view
    GLubyte *pixelBuffer = (GLubyte *)malloc(
                                             4 *
                                             textureView.bounds.size.width *
                                             textureView.bounds.size.height);

    // create a suitable CoreGraphics context
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context =
    CGBitmapContextCreate(pixelBuffer,
                          textureView.bounds.size.width, textureView.bounds.size.height,
                          8, 4*textureView.bounds.size.width,
                          colourSpace,
                          kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colourSpace);

    // draw the view to the buffer
    [textureView.layer renderInContext:context];

    // upload to OpenGL
    glTexImage2D(GL_TEXTURE_2D, 0,
                 GL_RGBA,
                 textureView.bounds.size.width, textureView.bounds.size.height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);



    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);



    glGenBuffers(1, &texArray);
    glBindBuffer(GL_ARRAY_BUFFER, texArray);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0,0);
    glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords), TexCoords, GL_STATIC_DRAW);
the_critic
  • 12,720
  • 19
  • 67
  • 115
  • What doesn't work? Better description of what issue shows will help people to answer your question. – DarthMike Jan 04 '13 at 14:59
  • Sorry @DarthMike. I just wanted to add some information. The image seems very blurry and any UILabel I add onto the view is blurry as well... – the_critic Jan 04 '13 at 15:01
  • Is this working in iPhone 4 retina as well? (not blurry) Because the content scale should be the same for iPhone 5, as screen only has more pixels in y. – DarthMike Jan 04 '13 at 15:06
  • It looks pretty much the same on iPhone 4 (retina). – the_critic Jan 04 '13 at 15:15
  • @DarthMike The strange thing is, when I set the parameter for GL_TEXTURE_WRAP_S and/or GL_TEXTURE_WRAP_T to GL_REPEAT it does not show anything at all. – the_critic Jan 04 '13 at 15:30
  • Could it be as simple as trying different size options in "Simulated Metrics" of the "Attributes Inspector" in the xib? i.e. "Retina 4 full screen" vs "Retina 3.5 full screen" – avenger Jan 31 '13 at 14:17

2 Answers2

0

My guess is that you need to update your texture to have double resolution.

You should load different texture altogether when working with retina resolution, as screen has double resolution for same coordinates. That's why you see blurry texture (scaled 2x). You must create buffers with twice x and y size for retina, by reading [UIScreen mainScreen].scale. I give you a tentative code, may not work as I could not test it:

MyView *view = [[MyView alloc]initWithFrame:CGRectMake(0, 0, 320, 80)];

self.effect.texture2d0.enabled = true;

//Pixel to coord scale
GLFloat coordToPixScale = [UIScreen mainScreen].scale;

// make space for an RGBA image of the view
GLubyte *pixelBuffer = (GLubyte *)malloc(
                                         4 *
                                         view.bounds.size.width * coordToPixScale *
                                         view.bounds.size.height * coordToPixScale);

// create a suitable CoreGraphics context
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context =
CGBitmapContextCreate(pixelBuffer,
                      view.bounds.size.width*coordToPixScale, view.bounds.size.height*coordToPixScale,
                      8, 4*view.bounds.size.width *coordToPixScale,
                      colourSpace,
                      kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colourSpace);

// draw the view to the buffer
[view.layer renderInContext:context];

// upload to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,
             GL_RGBA,
             view.bounds.size.width * coordToPixScale, view.bounds.size.height * coordToPixScale, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);

BOOL repeatX = NO;
BOOL repeatY = NO;

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatX ? GL_REPEAT
                       : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatY ? GL_REPEAT
                       : GL_CLAMP_TO_EDGE);



glGenBuffers(1, &texArray);
glBindBuffer(GL_ARRAY_BUFFER, texArray);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0,0);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords), TexCoords, GL_STATIC_DRAW);
DarthMike
  • 3,471
  • 1
  • 22
  • 18
  • My only guess then is that contentScale in layer should be 1.0. – DarthMike Jan 04 '13 at 16:07
  • now it looks twice as horrible as before... so I think your answer does the trick in terms of how it looks (nearly perfect) but it is half the size... However the contentScale has to remain 2.0 because when I set it to 1.0 it looks absolutely horrible – the_critic Jan 04 '13 at 16:15
0

SOLUTION FOUND !

Please take a look at this question:

OpenGL ES 2.0 textures for retina display?

Community
  • 1
  • 1
the_critic
  • 12,720
  • 19
  • 67
  • 115