Why is it that when I zoom in the frameRate drops massively?

I wrote a game where when you increase the zoom factor by even the slightest, the frameRate drops massively until it barely renders the next frame anymore;
weirdly, that doesn’t occur when zooming out. reversely, zooming out stabilizes the frame rate even a little bit.

There are quite a few images to be drawn onscreen;
which in turn are being scaled by g.image( PImage, float, float, float, float, int, int, int, int )

now is there any expense in upscaling images or should i look into a leak in my code?

Hey There!

Upscaling the image causes more pixels to be present unless you render only the pixels on screen it is plausible that it will have a large FPS drop.

yes, and using that remap way of
image(img,x,y,w,h…)
at every draw loop is a lot of “work”
but possibly you can try to take the stress out of it:

  • -a- at the moment when you change the ZOOM… you make a scaled copy of the
    image
  • -b- and then only show that copy with
    image(imgcopy,x,y);

I am only rendering everything that is onscreen tho, which are around 10 images. There is nothing offscreen yet, and I am not even checking, this would probably slow it down even further considering some objects are rotated as well.

i am trying this.
but for b, i have sprites that have to extract a part of the image is there any method for not rescaling but still only taking a part of the img or do i have to write a custom one.

and if i have to write a custom, what would be the best method. iterate over the pixels and calculate the result argb?

I think giving us insight into your code would be quite helpful !

Sure, I’d love too.

My code is quite lengthy and messy though, so I don’t expect anyone want to read through it.

Here I have linked my rewritten version, where images are scaled and cached when the zoom changes.

Files starting with A are an Addition from the current application.
Files starting with B make up the Base, beneficial code that eases my programming endeavours.

class ScaImage in BImage has 2 PImage & 1 float.
1 image is the base image, 1 image is the scaled image and the float is the scale factor.
If the current zoom factor is not the same as the scale factor, it updates the scaled image and the stored scale factor.

For sprite sheets of low resolution this does create some unpleasant edge behaviour though, so maybe I want to not scale down since scaling down doesn’t seem to have a negative framerate impact anyway.

I am still using g.image( img, dx, dy, dw, dh, sx, sy, sx2, sy2 )
bc some images are drawn in reverse ( swap sx & sx2 ) and the others use sprite sheets so i need to extract the image.
ofc i could also load the images from the sprite sheets into separate image objects, that would solve the problem as well

You can also try running the sketch and look at the FPS in the console.
mouse wheel zooms in and out.

If there are any questions of course feel free to ask.

Woah your code is real spaghetti ! I would honestly advise you to rewrite it. And utilize S4P it a life saver I been using it for my project . On top of that you should try load your images as a sheet rather than separate entities for bookkeeping reasons. But what it seems for me is that your using .get() that quite costly from what I know what would be better is just to expand and retract the size of the images such as:

PImage example;
int normalSize;
void setup(){
  size(600,600);
  example = loadImage("box.png");
  normalSize = 5;
}
void draw(){
  background(0);    
  image(example,width/2,height/2,normalSize,normalSize);
}
void mouseDragged(){
  normalSize+=10;    
  println(frameRate);
}

Contact me privately and I can arrange helping you out to rewrite the code !

Sure, how can I contact you privately? Discord?

Other than that, what is costly about get()?

What I used before was g.image( img, dx, dy, dw, dh, sx, sy, sx2, sy2 ) which caused lag when scaling up.

So that’s why I implemented this, lazily caching the scaled version whenever the zoom is changed.
But I still didn’t find a method that let’s you extract a part of the image without rescaling it.
d.h. g.image( img, x, y, sx, sy, sx2, sy2 )
of course i could do sx2 - sx and sy2 - sy to calculate the w, h values and use g.image( img, dx, dy, dw, dh, sx, sy, sx2, sy2 ).
I didn’t look into the source of g.image( img, dx, dy, dw, dh, sx, sy, sx2, sy2 ) but I would expect that it checks if the w / h are the same and in that case not perform the rescaling calculation.

I just tried it out with this sketch and it seems very much like @kll’s assumptions were on point.

If the image has to be rescaled and the rescaled version is fairly large, covering a good amount of pixels, it becomes very costly it seems like.

If I swap to the pre-scaled images and use the method without the width and height parameters, or pass the rescaled images exact width and height as arguments, it doesn’t cause high frame rate drops.
If I change the width or height parameter though, e.g. by adding 1 to width, the frame rate plummets once again as long as the image is large.
The rescaling method seems to cast the float values for width & height to int and then compare them to the image’s actual width & height to determine if rescaling is necessary.

Without looking at the source of g.image( img, x, y, w, h ), it probably iterates over all the pixels of the target size of the scaling calculation ( z = w * h, z pixels ).

I wrote a game in plain java before using java’s awt library and rescaling on every frame, I didn’t recall having lags there, but perhaps I was running on a lower frame rate there as well ( I think it was 30 or 24, I brought it down because it was turn-based ).
And it was everything on a fairly small scale as well and when I zoomed in a lot it seemed to get a little slower as well.

Since the rescaling method seems to “optimize” when the source wh matches the target wh, I’ll try g.image( img, x, y, w, h, sx, sy, sx2, sy2 ) with the exact wh parameters.
Of course it would be optimal if there was the same method without the w, h parameters so maybe I’ll write a custom one, but it’s probably not worth my time for optimizing away two comparisons.

EDIT:

I just realized that it is even more suboptimal than I expected.
The frameRate also drops if you just extract a part of the image or draw an image in reverse even if the width and height still match and no rescaling in that sense would be necessary.