treeform / boxy

2D GPU rendering with a tiling atlas.
MIT License
102 stars 7 forks source link

Help: scale to screen #56

Closed konsumer closed 1 year ago

konsumer commented 1 year ago

I have a very small window (320x240) and when I fullscreen it keeps showing things in the bottom-left corner. Is there any way to efficiently scale to the screen-size, maintaining the aspect ratio?

treeform commented 1 year ago

Are you sure you are calling bxy.beginFrame(window.size) with correct size every frame? What OS are you using? Can you produce a simple example of this issue?

konsumer commented 1 year ago

Are you sure you are calling bxy.beginFrame(window.size) with correct size every frame?

Ah, yes, I think may be part of it, I was using a set ivec2(320, 240) (as in README) not window.size. Checking window.size I get ivec2(3360, 2100)

Can you produce a simple example of this issue?

I updated to use window.size, and it still shows small image in upper-left corner:

import boxy, opengl, windy

let windowSize = ivec2(320, 240)

let window = newWindow("Windy + Boxy", windowSize)
makeContextCurrent(window)

loadExtensions()

let bxy = newBoxy()

bxy.addImage("ring1", readImage("ring1.png"))
bxy.addImage("ring2", readImage("ring2.png"))
bxy.addImage("ring3", readImage("ring3.png"))

var frame: int

while not window.closeRequested:
  bxy.beginFrame(window.size)
  let center = windowSize.vec2 / 2
  bxy.drawImage("ring1", center, angle = frame.float / 100)
  bxy.drawImage("ring2", center, angle = -frame.float / 190)
  bxy.drawImage("ring3", center, angle = frame.float / 170)
  bxy.endFrame()
  window.swapBuffers()
  inc frame
  pollEvents()

The images are your demo-images, resized to 240x240.

I am on Intel Macbook, running Ventura 13.2.1.

Here is a screenshot in fullscreen:

Screenshot 2023-04-10 at 11 50 25 PM

What I am hoping for is to fill the screen, scaled to screen-size, maintaining aspect.

konsumer commented 1 year ago

If I do this without boxy, just using pixie/shader, it's a bit closer, but still stretches to fullscreen: tester.nim.zip

konsumer commented 1 year ago

For further troubleshooting, here is a simple demo that has problem.

Test with nimble run

More info:

What I want is to be able to pretend the screen is always 320x240 and have it scale to fit in a reasonable way, at any size.

Normal (looks good):

Screenshot 2023-04-11 at 10 14 13 PM

Resized window (did not scale to window size):

Screenshot 2023-04-11 at 10 14 44 PM

Fullscreen is similar to Resized.

konsumer commented 1 year ago

Ok, I got it. I didn't know about bxy.scale and bxy.translate (your API docs are down, by the way.)

I ended up doing this and it totally worked:

let ratio = windowSize.x / windowSize.y
var scale = 1.0
var offset = vec2(0, 0)

var fX:float
var fY:float

window.onFrame = proc() =
  fX = float(window.size.x)
  fY = float(window.size.y)
  if float(window.size.x) > (fY * ratio):
    scale = window.size.y / windowSize.y
    offset.x = (fX - (float(windowSize.x) * scale)) / 2
    offset.y = 0
  else:
    scale = window.size.x / windowSize.x
    offset.y = (fY - (float(windowSize.y) * scale)) / 2
    offset.x = 0

  bxy.beginFrame(window.size)
  bxy.saveTransform()
  bxy.translate(offset)
  bxy.scale(scale)

  bxy.drawRect(rect(vec2(0, 0), windowSize.vec2), color(0.3, 0.3, 0.3, 1))
  bxy.drawImage("heart", vec2(0, 0))

  bxy.restoreTransform()
  bxy.endFrame()
  window.swapBuffers()

while not window.closeRequested:
  pollEvents()
Screenshot 2023-04-12 at 12 54 58 AM Screenshot 2023-04-12 at 12 55 05 AM

works great in fullscreen, too.