MacOS – How to display text in OpenGL on Mac OS using Retina

I am using OpenGL to draw in Mac OS. When my code runs on a Retina display, everything works fine, except for text drawing.
Under the retina display, the text is it It should be twice as large. This happens because the font size is in points, and each point is 2 pixels in Retina, but OpenGL is pixel-based.

This is the correct text drawing under the standard display:

This is the incorrect text drawing under the Retina display:

This is how I officially draw the string. Because of OpenGL There is no text drawing function, in order to draw text, I do the following:

>Get font:

NSFontManager fontManager = [NSFontManager sharedFontManager];
NSString font_name = [NSString stringWithCString: “Helvetica” encoding: NSMacOSRomanStringEncoding];
font = [fontManager fontWithFamily: font_name traits: fontStyle weight: 5 size: 9];
attribs = [[NSMutableDictionary dictionaryWithCapacity: 3] retain];
[attribs setObject :Font forKey:NSFontAttributeName];
>Create and measure a string:

NSString * aString = [NSString stringWithCString: “blah blah” encoding: NSMacOSRomanStringEncoding];
NSSize frameSize = [aString sizeWithAttributes :M_attribs];
>Use size to allocate NSImage:

NSImage * image = [[NSImage alloc] initWithSize: frameSize];
[image lockFocus];
>Draw a string Into the image:

[aString drawAtPoi nt: NSMakePoint(0,0)withAttributes: m_attribs];
>Get bits:

NSBitmapImageRep * bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect: NSMakeRect(0.0f,0.0f,frameSize.width, frameSize.height)];
[image unlockFocus];
>Create OpenGL texture:

GLuint texture = 0;
glGenTextures(1,& texture);
glTexImage2D( GL_TEXTURE_RECTANGLE_EXT,0,GL_RGBA,GLsizei(frameSize.width),GLsizei(frameSize.height),0,GL_RGBA,[bitmap bitmapData]);
>Drawing texture:

glBindTexture ……
Other OpenGL drawing codes

My question is how to make NSString draw in pixel resolution instead of points.

I tried the following methods:

> Draw at half the point size: 4.5 instead of 9. This gives me the correct size, but the text draws blurry.
>Draw at the point size and shrink the texture to half the size of OpenGL, again this won’t give Good-looking results:

OpenGLs coordinate system is actually based on points rather than pixels, but You decide what these points are. The context defines the coordinate system in 2D through the glOrtho function (or you can manually construct an orthogonal matrix), which sets the minimum and maximum x, y coordinates on the screen. For example, you can set an orthogonal projection such that 0 is on the left side of the screen and 100 is on the right, regardless of the size of the frame buffer you render.

The font texture seems to be created very well. The problem is the size you render it on the geometry It is twice as much as it needs. In OpenGL, the texture size does not affect the size of the object rendered on the screen. The size on the screen is defined by the geometry passed to glDrawArrays or glBegin, etc., not the texture.

I think the problem is that you use the pixel size of the font texture to define the size of the quad for rendering on the screen This will put your question in the “Other OpenGL drawing code” section. To solve this problem, you can apply some kind of scale factor to the drawing. In retina mode, the scale factor is 0.5, for normal screens, it will be 1.0 (UIKit uses a similar idea to present UIView content)

The quadruple calculation may look like this:

quad.width = texture.width * scaleFactor 
quad.height = texture.height * scaleFactor

Another option is to completely separate the quadrangle rendering size from the texture. If you have a function or class to draw text, it can have one The font size parameter, it will be used as the actual quad size instead of using the texture size.

I am using OpenGL to draw in Mac OS. When my code is on a Retina display When running on the above, everything is normal, except for the text drawing.
Under the retina display, the text is twice as large as it should be. This happens because the font size is in points, and each point is There are 2 pixels under Retina, but OpenGL is pixel-based.

This is the correct text drawing under standard display:

This is incorrect under Retina display Text drawing:

This is my official way of drawing strings. Since OpenGL has no text drawing function, in order to draw text, I do the following:

>Get fonts:

NSFontManager fontManager = [NSFontManager sharedFontManager];
NSString font_name = [NSString stringWithCString: “Helvetica” encoding: NSMacOSRomanStringEncoding];
font = [fontManager fontWithFamily: font_name traits: fontStyle weight: 5 size: 9] ;
attribs = [[NSMutableDictionary dictionaryWithCapacity:3] retain];
[attribs setObject:font forKey:NSFontAttributeName];
>Create and measure a string:

NSString * aString = [NSString stringWithCString: “blah blah” encoding: NSMacOSRomanStringEncoding];
NSSize frameSize = [aString sizeWithAttributes: m_attribs];
>Use size allocation NSImage:

NSImage * image = [ [NSImage alloc] initWithSize:frameSize];
[image lockFocus];
>Draw a string into an image:

[aString drawAtPoint:NSMakePoint(0,0)withAttributes:m_attribs] ;
>Get bits:

NSBitmapImageRep * bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect: NSMakeRect(0.0f,0.0f,frameSize.width,frameSize.height)];
[image unlockFocus ];
>Create OpenGL texture:

GLuint texture = 0;
glGenTextures(1,& texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT,0,GL_RGBA,GLsizei(frameSize.width) ,GLsizei(frameSize.height),0,GL_RGBA,[bitmap bitmapData]);
>Drawing texture:

glBindTexture ……
Other OpenGL drawing codes

I The question is how to make NSString draw in pixel resolution instead of points.

I tried the following methods:

>Draw at half the point size: 4.5 instead of 9. This gives me the correct size, but the text is drawn blurry.
>Draw at the point size and reduce the texture to half the size of OpenGL, again this will not give good results:

OpenGLs coordinate system is actually based on points rather than pixels, but you decide what these points are. The context defines the coordinate system in 2D through the glOrtho function (or You can manually construct an orthogonal matrix), which sets the minimum and maximum x, y coordinates on the screen. For example, you can set the orthogonal projection so that 0 is on the left of the screen and 100 is on the right, regardless of the frame buffer you render How about the size.

The font texture seems to be created very well. The problem is that you render it on the geometry twice the size it needs. In OpenGL, the texture size does not affect the rendering on the screen The size of the object. The size on the screen is defined by the geometry passed to glDrawArrays or glBegin, etc., not the texture.

I think the problem is that you use the pixel size of the font texture to define for rendering on the screen The size of the quadrilateral. This will put your question in the “Other OpenGL drawing code” section. To solve this problem, you can apply some kind of scale factor to the drawing. In the retina mode, the scale factor is 0.5. For normal screens, It will be 1.0 (UIKit uses a similar idea to present UIView content)

The quadruple calculation may look like this:

quad.width = texture .width * scaleFactor 
quad.height = texture.height * scaleFactor

Another option is to completely separate the quadrangle rendering size from the texture. If you have a function or class to draw text, it There can be a font size parameter, which will be used as the actual quad size instead of using the texture size.

Leave a Comment

Your email address will not be published.