[SOLVED] How to really resize a Sprite (to avoid scaling it)

Hi all,

I want to create a sprite from a image with different dimensions from the image. For example image.png is 200x200, and I want to create a sprite of 100x100 with the same image resized.

I donā€™t want to use setScale (0.5);

I want the sprite with size 100x100 and scale 1.0;

No problem if I use setScale in the middle of the process to resize my Image/Sprite. But the final sprite I want scale 1.0, and the image in memory is 100x100, to avoid scaling.

I had similar situation.
I just added sprite to an empty node.
sprite scale is 0.5 and empty node is 1.0.

I not sure thereā€™s another way to solve it.

Hi hzlov, thanks for the answer. But this doesnā€™t solve my problem.

What I want is the real image in a different size, Avoiding scaling the image, and therefore improving the performance.

If you have an image scaled as as child of another node, the image is still scaled.

To clarify. What I want is as if I had read a 100x100 image of the disk. And not a 200x200 and scaling it. Because in this second way you lose performance.

Problem solved. Iā€™ve used RenderTexture to create a new Sprite from the original resized.

In this way, my game has all the final images in the perfect size to fit any screen, without scaling them, and the performance has been improved a lot. And I donā€™t need different sizes of the images, only one with big resolution.

RenderTexture can also be used to solve problem if anyone is having problem of performance when rotating big images, or other kind of slow rendering.

1 Like

would you like to elaborate more about ā€œscale without scalingā€ technique youā€™re using with rendertexture. Some example code will be appreciated :smile:

It seems very interesting, thank you for the idea (with an example would be awesome :smiley: )

Sample code will be awesome :smile:

Here an example for background image, of course you have to create a class to automate this, not implementing in each image:

// Screen real dimensions
auto vSize = Director::getInstance()->getVisibleSize();
auto vWidth = vSize.width;
auto vHeight = vSize.height;

// Original image
auto backOrig = Sprite::create( ā€œback_3200x2000.pngā€ );
auto oWidth = backOrig->getContentSize().width;
auto oHeight = backOrig->getContentSize().height;
backOrig->setFlippedY( true );
backOrig->setScale( vWidth / oWidth, vHeight / oHeight ); // backOrig scaled to screen size
backOrig->setPosition( vWidth / 2, vHeight / 2 );

// Create new texture with background in the exact size of the screen
auto renderTexture = RenderTexture::create( vWidth, vHeight, Texture2D::PixelFormat::RGBA8888 );
renderTexture->begin();
backOrig->visit();
renderTexture->end();

// Create new Sprite without scale, which perfoms much better
auto backOk = Sprite::createWithTexture( renderTexture->getSprite()->getTexture() );
backOk->setPosition( vWidth / 2, vHeight / 2 );
addChild( backOk );

9 Likes

Impressive! Thank you!

I do not understand why are you doing this in real time. Why not give directly an image of 100x100 in your case?

It will work fine for normal pngs but
Low end devices will not be able to load high textures.
If you are targeting low/mid end android devices.

Strange ?? you still need to scale Original to screen sized, then let it render to RenderTexture buffer (not sure if i understand correctly)

So instead of setScale and drawing directly to screen, you setScale and draw it to RenderTexture, does this profit any performance?

@Dredok @nbtthief To reduce art assets

so?
Why doing this resize in real time? if you know that you will need to scale down an art asset, just do it offline in the ā€œcookingā€ stage. It makes no sense to ship a game with an asset which you will always process in the same way (scaling down) instead of shipping it with an already scaled down assetā€¦

ā€œI do not understand why are you doing this in real time. Why not give directly an image of 100x100 in your case?ā€

Because. I would have to have one image for each screen size, or some image sizes, scale them, and lose performance.

ā€œSo instead of setScale and drawing directly to screen, you setScale and draw it to RenderTexture, does this profit any performance?ā€

If you use set scale in the Sprite that is added to scene, it is scaled In every frame rendering, so it take more time to render. Iā€™ve tested in a S3 mini and the difference is enormous.

ā€œWhy doing this resize in real time? if you know that you will need to scale down an art asset, just do it offline in the ā€œcookingā€ stage. It makes no sense to ship a game with an asset which you will always process in the same way (scaling down) instead of shipping it with an already scaled down assetā€¦ā€

The scale down, is to scale to the EXACT size of the device. And devices have different sizesā€¦

2 Likes

Soā€¦ donā€™t you use Director::getInstance()->getOpenGLView()->setDesignResolutionSize()?

Yes. To gain performance I donā€™t use it. I resize all the images proportionally to visibleSize. This method is only useful if you are having problems with performance. For example, big images with alpha in slow devices.

Of course, I also have methods to position the images proportionally.