I opted to use the current released version (v0.17.1) but it’s currently undergoing a significant rearchitecture so I may move to that whenever it releases.
First thing I did was look for a tutorial, of which there really aren’t many. If you’re familiar with gfx, even a small tutorial would probably be really helpful for beginners. Anyway, I found this one and followed it fairly closely.
Dust settles and I have an ugly fullscreen quad:
Cool, now let’s resize the window and-
Huh… that’s not very fullscreen. To make this work properly, we need to listen for the Resized event, then apply the new size to the window and views:
That’s an improvement - the contents of the window are resizing now. But ideally, I want the game to always render at the same aspect ratio. Namely 16:9. If the window is too tall, I want it to letterbox, and if it’s too wide, to pillarbox.
To accomplish that, we need two things: a scissor test to restrict rendering to a specific rectangle, and a viewport transformation to rescale whatever is being rendered so that it fits within that scissor rectangle.
(These two can be accomplished together by setting the viewport, which is possible in glium, but not currently supported by gfx.)
Setting up the scissor test is extremely easy. You just need one addition to the pipeline definition:
And also one addition to the pipe data:
The question now is how do we determine the rectangle we want to draw in. We want the largest 16:9 rectangle we can fit in the window, so there are two possibilities: the rectangle as tall as the window, or the rectangle as wide as the window.
So for our first rectangle, we can assume its height is the same as the window. We then multiply by the aspect ratio (16/9) to get the width of that rectangle.
Our second rectangle has the same width as the window. Similarly, to get the height, we divide by the aspect ratio (multiply by 9/16).
One of these will fit the window, and the other one will be too large - depending on whether our window’s aspect ratio is smaller or larger than 16:9. We just have to take the smallest one. In the code below, we do this by choosing the smallest width of the two, and the smallest height of the two independently, but it’s the same result.
So here’s what the code for that looks like:
Looks good to me! We always have the largest possible viewport with the correct aspect ratio. But notice how different parts of the quad are displayed for different viewports. That’s because we aren’t scaling the contents of the viewport to fit the scissor rect. Luckily this is pretty simple.
Essentially, we want to scale down the output of our vertex shader to fit the viewport. If the viewport is half as wide as the window, we want to scale it horizontally by half. If it’s a tenth as tall, we want to scale it vertically by a tenth, etc.
Yep. Good. Perfect.
So that’s something pretty basic, but also important to get right. Maybe next time I’ll draw something more interesting on screen.