iPhone 6s / RoboVM(?)GLTexImage2D渲染问题(iPhone 6s / RoboVM (?) GLTexImage2D rendering issue)

编程入门 行业动态 更新时间:2024-10-22 04:48:42
iPhone 6s / RoboVM(?)GLTexImage2D渲染问题(iPhone 6s / RoboVM (?) GLTexImage2D rendering issue)

我们终于在App Store上发布了我们的独立游戏,发现我们在iPhone 6s上存在重大的渲染问题。

该游戏是使用LibGDX和RoboVM开发的(第1.1节)

我们使用iOS原生图形库将unicode文本渲染到纹理,以将其传递给LibGDX以显示为图像。 为此,我们首先创建要打印的字符串,然后调用其draw()方法:

final String tmp = text.substring(0, text.length() >= MAX_NAME_LEN ? MAX_NAME_LEN : text.length()); final NSMutableString string = new NSMutableString(tmp.length()); //Allocate space for the bitmap to draw on int w = (int) width; int h = (int) height; final int bufferLen = w * h; final CGBitmapContext context = new CGBitmapContext( w, h, 8, 0, CGColorSpace.deviceRGB(), CGImageAlphaInfo.PremultipliedLast ); final CGColor bgColor = UIColor.clear().getCGColor(); final CGRect rect = new CGRect(0, 0, width, height); string.setString(tmp); final UIColor textColor = new UIColor(color.r, color.g, color.b, color.a); final UIFont font = UIFont.getBoldSystemFont(size); final NSString tester = new NSString("a"); final CGSize textSize = tester.getSize(font); int strLen = string.toString().length(); /** * Computes the optimal length of the string and removes characters beyound the * screen bounduaries. * If the string has been reduced, appends an ellipsis at the end */ final NSRange range = new NSRange(); boolean removed = false; while (strLen > 0 && textSize.getWidth() * strLen > width - textSize.getWidth() * 2) { range.setLocation(strLen - 1); range.setLength(1); string.deleteCharacters(range); strLen = string.toString().length(); removed = true; } //append ellipsis at the end if we removed a char if (removed) { string.append("\u2026"); } context.setFillColor(bgColor); context.fillRect(rect); //set up drawing attributes final NSAttributedStringAttributes attributes = new NSAttributedStringAttributes(); attributes.set(NSAttributedStringAttribute.Font, font); attributes.set(NSAttributedStringAttribute.ForegroundColor, textColor); final NSMutableParagraphStyle paragraphStyle = new NSMutableParagraphStyle(); paragraphStyle.setParagraphStyle(NSParagraphStyle.getDefaultParagraphStyle()); paragraphStyle.setLineBreakMode(NSLineBreakMode.TruncatingTail); attributes.set(NSAttributedStringAttribute.ParagraphStyle, paragraphStyle); final NSAttributedString finalStr = new NSAttributedString(string.toString(), attributes); UIGraphics.pushContext(context); context.setTextMatrix(CGAffineTransform.Identity()); context.translateCTM(0f, h); context.scaleCTM(1, -1); finalStr.draw(new CGPoint(rect.getX(), (rect.getY() + textSize.getHeight()) / 2)); UIGraphics.popContext(); return new BufferTextureData((int)context.getWidth(), (int)context.getHeight(), 0, GL20.GL_RGBA, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, context.getData().asIntBuffer(bufferLen));

然后,TextureBufferData以下列方式将Buffer绑定到纹理:

private Buffer data; public BufferTextureData(int width, int height, int mipMapLevel, int internalFormat, int format, int type, Buffer data) { this.width = width; this.height = height; this.mipLevel = mipMapLevel; this.internalFormat = internalFormat; this.format = format; this.type = type; this.data = data; } [...] @Override public void consumeCustomData(final int target) { Gdx.app.debug("BufferTextureData", "consuming data for target: " + target); Gdx.gl20.glTexImage2D(target, mipLevel, internalFormat, width, height, 0, format, type, data); data = null; }

我们在这些设备上测试了这段代码没有任何问题: - iPhone 6 - iPad Air 2 - iPhone 5s以及iPhone 6s模拟器。

问题是在iPhone 6s的实际设备上我们得到了这个:

如您所见,文本完全失真。 似乎在drawcall期间写入了包含绘图数据的缓冲区,但我们确保在绘图线程上调用该方法以避免GL上下文切换。

我们真的不知道在哪里寻找。 代码无缝地在iPhone6s Simulator(x64 CPU)和所有其他设备上运行这一事实使我认为问题是硬件依赖或由RoboVM处理内存的方式引起的,但这只是猜测。

有没有人遇到过同样的问题或对可能导致这种行为的原因有所了解?

提前致谢

we finally released our indie game on the App Store just to find that we have major rendering issues with iPhone 6s.

The game is developed using LibGDX and RoboVM (v.1.12)

We are using the iOS native graphics libraries to render unicode text to a texture to pass it to LibGDX to display as an image. To do so we first create the string we want to print and then call its draw() method:

final String tmp = text.substring(0, text.length() >= MAX_NAME_LEN ? MAX_NAME_LEN : text.length()); final NSMutableString string = new NSMutableString(tmp.length()); //Allocate space for the bitmap to draw on int w = (int) width; int h = (int) height; final int bufferLen = w * h; final CGBitmapContext context = new CGBitmapContext( w, h, 8, 0, CGColorSpace.deviceRGB(), CGImageAlphaInfo.PremultipliedLast ); final CGColor bgColor = UIColor.clear().getCGColor(); final CGRect rect = new CGRect(0, 0, width, height); string.setString(tmp); final UIColor textColor = new UIColor(color.r, color.g, color.b, color.a); final UIFont font = UIFont.getBoldSystemFont(size); final NSString tester = new NSString("a"); final CGSize textSize = tester.getSize(font); int strLen = string.toString().length(); /** * Computes the optimal length of the string and removes characters beyound the * screen bounduaries. * If the string has been reduced, appends an ellipsis at the end */ final NSRange range = new NSRange(); boolean removed = false; while (strLen > 0 && textSize.getWidth() * strLen > width - textSize.getWidth() * 2) { range.setLocation(strLen - 1); range.setLength(1); string.deleteCharacters(range); strLen = string.toString().length(); removed = true; } //append ellipsis at the end if we removed a char if (removed) { string.append("\u2026"); } context.setFillColor(bgColor); context.fillRect(rect); //set up drawing attributes final NSAttributedStringAttributes attributes = new NSAttributedStringAttributes(); attributes.set(NSAttributedStringAttribute.Font, font); attributes.set(NSAttributedStringAttribute.ForegroundColor, textColor); final NSMutableParagraphStyle paragraphStyle = new NSMutableParagraphStyle(); paragraphStyle.setParagraphStyle(NSParagraphStyle.getDefaultParagraphStyle()); paragraphStyle.setLineBreakMode(NSLineBreakMode.TruncatingTail); attributes.set(NSAttributedStringAttribute.ParagraphStyle, paragraphStyle); final NSAttributedString finalStr = new NSAttributedString(string.toString(), attributes); UIGraphics.pushContext(context); context.setTextMatrix(CGAffineTransform.Identity()); context.translateCTM(0f, h); context.scaleCTM(1, -1); finalStr.draw(new CGPoint(rect.getX(), (rect.getY() + textSize.getHeight()) / 2)); UIGraphics.popContext(); return new BufferTextureData((int)context.getWidth(), (int)context.getHeight(), 0, GL20.GL_RGBA, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, context.getData().asIntBuffer(bufferLen));

TextureBufferData then binds the Buffer to a texture in the following way:

private Buffer data; public BufferTextureData(int width, int height, int mipMapLevel, int internalFormat, int format, int type, Buffer data) { this.width = width; this.height = height; this.mipLevel = mipMapLevel; this.internalFormat = internalFormat; this.format = format; this.type = type; this.data = data; } [...] @Override public void consumeCustomData(final int target) { Gdx.app.debug("BufferTextureData", "consuming data for target: " + target); Gdx.gl20.glTexImage2D(target, mipLevel, internalFormat, width, height, 0, format, type, data); data = null; }

We tested this code without any issues on those devices: - iPhone 6 - iPad Air 2 - iPhone 5s And also on the iPhone 6s simulator.

The problem is that on a iPhone 6s actual device we get this:

As you can see, the text is completely distorted. It seems that the buffer holding the drawing data gets written during the drawcall but we made sure to call that method on the drawing thread to avoid GL context switches.

We really have no clue where to look for. The fact that the code seamlessly works on the iPhone6s Simulator (x64 CPU) and all the other devices makes me think that the issue is either hardware dependent or caused by the way RoboVM handles memory, but it's just a guess.

Does anyone has experienced the same issue or have an idea about what could cause this behaviour?

Thanks in advance

最满意答案

这是对齐和/或行跨步问题。 我建议你阅读glPixelStore手册及其GL_UNPACK_ ...参数。 在使用glTexImage加载之前,必须设置像素存储参数以匹配图像数据

Thanks @datenwolf for pointing us to a good direction.

The problem was somehow due to this "known bug" of the iphone 6s:

http://ios9news.net/fix-ios-9-apps-zoomed-in-on-iphone-6s/

that is, given the same resolution and ppi of the iphone 6, the 6s thinks that he is a bit wider. Thus our game units that were made as such to be POT multiples were of odd length in 6s devices (for example a width of 480px on an iphone 6 was 561px on an iphone 6s).

When we created a graphics context with CGContextCreate we didn't specified how many bytes per row to consider and we let the device to decide for us. It turned out that the OS was adding padding to each row, messing up all the stride and alignments.

The fix was to change:

final CGBitmapContext context = new CGBitmapContext( w, h, 8, 0, CGColorSpace.deviceRGB(), CGImageAlphaInfo.PremultipliedLast );

to:

final CGBitmapContext context = new CGBitmapContext( w, h, 8, 4 * w, CGColorSpace.deviceRGB(), CGImageAlphaInfo.PremultipliedLast );

更多推荐

本文发布于:2023-07-28 19:01:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1308154.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:RoboVM   iPhone   GLTexImage2D   issue   rendering

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!