如何让textureFromNode产生视网膜显示的纹理? [英] How to have textureFromNode produce texture for retina display?

查看:200
本文介绍了如何让textureFromNode产生视网膜显示的纹理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

平台:XCode 6.0 + iOS 7.0.4

Platform: XCode 6.0 + iOS 7.0.4

在iPad mini Retina上运行以下代码,并期待 tmpLbl 节点以相同地渲染,因为后者通过 textureFromNode 用前者的纹理初始化。在现实中 tmpLbl ,它是一个 SKLabelNode ,在视网膜解析,节点,它应该是一个副本,是模糊的,看起来是一个半尺寸的纹理的双倍的再现。

Running the following code on iPad mini retina and expect the image of tmpLbl and node to render identically because the latter is initialized with the texture of the former, via textureFromNode. In reality tmpLbl, which is an SKLabelNode, renders at retina resolution but node, which is supposed to be a copy, is blurry, appearing to be a double-scaled rendition of a half-sized texture.

我看到一个帖子建议将源( tmpLbl 在下面的示例中)放在场景上,但它没有差别,如示例所示。

I saw a post suggesting to put the source (tmpLbl in the sample below) on the scene but it makes no difference, as illustrated by the sample.

任何建议:
1.如何使用任何类型的方法使这个工作
2.如何使这个工作没有源节点(下面的tmpLbl)曾经呈现在屏幕上

Any advice on: 1. how to make this work using any sort of approach 2. how to make this work without having the source node (tmpLbl below) ever rendered on the screen

示例代码:

- (void)didMoveToView:(SKView *)view {
    SKLabelNode *tmpLbl = [SKLabelNode labelNodeWithFontNamed: @"Futura"];
    tmpLbl.position = CGPointMake(100, 100);
    [self addChild: tmpLbl];

    tmpLbl.fontSize = 125;
    tmpLbl.fontColor = [SKColor colorWithRed:0.8 green:0.0 blue:0.0 alpha:1.0];
    tmpLbl.text = @"a";

    SKTexture *texture = [view textureFromNode: tmpLbl];
    SKNode *node = [SKSpriteNode spriteNodeWithTexture:texture];
    node.position = CGPointMake(200, 130);
    [self addChild:node];
    return;
}

渲染结果;左侧a是通过SKLabelNode,右侧是通过textureFromNode和spriteNodeWithTexture:

Rendering result; the left side "a" is via SKLabelNode, the right side one is via textureFromNode and spriteNodeWithTexture:

推荐答案

解决问题的方法:足以让源节点树传递给 textureFromNode 成为其他人建议的场景的一部分。返回的纹理是视网膜分辨率的另一个条件是 textureFromNode:被调用不是早于(我的实验的结果)比第一次调用 SKScene update:。 (更新:在XCode 5.0.1 textureFromNode:必须在第二次调用 update:期间或之后调用; textureFromNode 在第一次调用时仍会产生非视网膜纹理。)

Solution to the problem: it is necessary but not sufficient for the source node-tree passed to textureFromNode to be part of the scene as suggested by others. Another condition for the returned texture to be of "retina resolution" is that textureFromNode: is called not earlier (per the results of my experiments) than the first call to SKScene update:. (Update: on XCode 5.0.1 textureFromNode: must be called in during or after the second call to update:; textureFromNode during the first call still produces non-retina texture.)

只需移动上述问题中的代码到更新:函数,生成的纹理将具有视网膜渲染的所有像素。令人沮丧的是,纹理将是源节点(树)在两个方向上的大小的两倍,并且用返回的sprite初始化一个新的sprite将产生一个双倍大小的sprite(使用插值渲染)。很明显,SKTexture类有一个内部的scale属性,就像UIImage。当从带有'@ 2x'后缀的文件创建纹理时,SpriteKit设置此属性,而当通过 textureFromNode 创建纹理时,则不设置此属性。这是非常不幸的,因为这迫使应用程序开发人员手动跟踪比例,除非纹理是从图像资源创建的。

Just by moving the code in the question above to the update: function the resulting texture will have all the pixels for retina rendering. What is frustrating is that the texture will be double the size of the source node (tree) in both directions and initializing a new sprite with the returned sprite will produce a double-size sprite (that is rendered with interpolation). It is clear that the SKTexture class has an internal 'scale' property, just like UIImage. SpriteKit sets this property when creating the texture from a file with the '@2x' suffix but not when the texture is created via textureFromNode. This is very unfortunate because this forces the application developer to track the scale manually unless the texture is created from an image resource.

下面更新的示例包括以下更改原始的问题:

The updated sample below includes the following changes compared to the original in the question:


  • move textureFromNode:代码)到 update:;

  • 检测显示分辨率是否为视网膜,如果需要,将新sprite的大小调整为source-sprite的大小
  • li>
  • move textureFromNode: (along with the rest of the code) to update:; anyone has a better place that would still produce a retina-size rendition?
  • detect if the display resolution is retina and resize the new sprite to the size of the source-sprite if needed

通过这些更改,两个a图像呈现相同。

With these changes the two 'a' images are rendered identically.


// retina resolution will be not applied if textureFromNode is called before SKScene::update():
-(void)update:(CFTimeInterval)currentTime {
    static int cnt = 0;

    if (cnt == 1) // can be cnt == 0 on XCode 6.0
    {
        double scale=1.0;
        if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0)) {
            // the texture returned by textureFromNode is double-size on retina displays; must explicitly make the sprite half the size of the texture:
            scale=0.5;
        }

        SKLabelNode *tmpLbl = [SKLabelNode labelNodeWithFontNamed: @"Futura"];
        tmpLbl.position = CGPointMake(100, 100);
        // must be part of the scene or else retina resolution will be not applied:
        [self addChild: tmpLbl];

        tmpLbl.fontSize = 125;
        tmpLbl.fontColor = [SKColor colorWithRed:0.8 green:0.0 blue:0.0 alpha:1.0];
        tmpLbl.text = @"a";

        SKTexture *texture = [self.view textureFromNode: tmpLbl];
        SKNode *node = [SKSpriteNode spriteNodeWithTexture:texture size: CGSizeMake(texture.size.width*scale, texture.size.height*scale)];
        node.position = CGPointMake(200, 130);
        [self addChild:node];

        // was added to the scene only to force retina resolution rendering:
        // [tmpLbl removeFromParent];
    }
    ++cnt;
}

使用更新的代码渲染结果。右侧图片不再模糊:

Rendering result with the updated code. The right-hand-side image is not blurry anymore:

这篇关于如何让textureFromNode产生视网膜显示的纹理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆