More graphical tweaking

I should be working on Flight, but instead I've been tuning the heck out of some of the visual faff in the existing tracks, because I can't leave well enough alone.

In Little Bouncing Ball I restored a prior bit of functionality where the RoamingEye reflected the entire screen and not just itself, meaning they can also reflect each other, their aiming reticules, the scoreboard, and the water. All those subtle differences are visible in the posted screenshot crop; you can barely see the big one reflected in the little one, and its aiming beam and the water reflected in both and the scoreboard reflected in the big one. (In this particular instance the water is too calm for any ripples to be visible in the reflections, but the still waters manifest as the slightly blue halo around the edges.)

In Strangers I decided that the CRT scaler was a little too ad-hoc and resolution-sensitive, so I pulled out some integral calculus to make it actually properly integrate in a continuous manner. While I was at it I tuned the sizing of the shadow mask (still keeping it as an emulation of the Sony Trinitron mask, mostly because the math is easier, but also because my attempts at emulating the RCA pattern didn't end up looking very, you know, good) and also made the actual beam a bit narrower.

I do want to talk a bit about one of my pet peeves when it comes to scanline emulation. And CRT emulation in general. People seem to just slap any arbitrary RGB-ish grid plus horizontal lines on top of the image and call it a day. But there's a lot more going on here. The scanlines are an artifact of how 240p outputs work, and so the bands are brightest in the middle of each pixel's scanline, with a Gaussian-esque falloff. (480i fills in those gaps with every other field, and so you don't actually see the scanlines on 480i sources such as VCRs and so on.)

Also the shadow mask is in no way associated with the pixel resolution of the source image!

And finally, the pixel blurring only happens horizontally. For the purpose of this scaler I have blended between a horizontally-linearly-interpolated image and a nearest-neighbor image, with the transition bands being a fairly small segment across the horizontal pixel boundaries. It's not QUITE accurate but it's Close Enough for me.

In this shader, the shadow mask resolution is totally independent of the source pixels (it roughly emulates a .5mm horizontal dot pitch on a 14" diagonal CRT - a real CRT would be more like .25mm but that makes the effect a little too understated for my tastes), and the scanline effect is based on an approximation of the Gaussian, centered vertically on the pixel. Just as it should be.

It uses entirely too much trigonometry for my tastes but when I do an optimization pass in the future I can fix this. It performs just fine on my (admittedly fairly high-end!) desktop's GPU, though.

In any case, the emulated CRT should be pretty accurate to a 256x224 pixel 4:3 image sent through s-video to a Trinitron-tube consumer-grade CRT using 240p-style retrace, with the assumption that the 16 lines of overscan get perfectly cropped.  I kind of wanted to do a composite video simulation on top of that but that's getting into the realm of the rather complicated to do right, so maybe I can do that later when I've gotten another hair up my butt. (I probably won't.) I did take some liberties with the shadow mask calculations to reduce the actual contrast and to make the math easier to integrate and so on but unless you're rendering it at like 10K and looking at it through a magnifying glass it should be pretty close, I think?

Other changes since the last devlog:

  • Internal stuff: wrote my own dang profiler (because Piefiller wasn't really doing it for me anymore); it doesn't do a few things I want but it's closer to being what I care about at least (I really wish I could get some better GPU timing reporting out of LÖVE though)
  • Changed the dynamic resolution algorithm to better handle vsync estimation
  • As a result of the above, it started running just fine in hidpi mode on my laptop so I've turned hidpi on by default (for supported computers of course; without a hidpi monitor LÖVE should still assume 100dpi)

Also I haven't been completely neglectful of Flight! Mostly I'm trying to figure out the best way to reason about the coordinate system, trying to balance the needs of various aspect ratios. I have come up with a solution I'd be happy with, if only I can get LÖVE's coordinate transform system to cooperate...


macOS, x86 64-bit 43 MB
Version Dec 15, 2017
Windows, x86 64-bit 30 MB
Version Dec 15, 2017
Windows, x86 32-bit 30 MB
Version Dec 15, 2017
LÖVE bundle (requires LÖVE 0.10.2) 26 MB
Version Dec 15, 2017

Get Refactor

Buy Now$3.00 USD or more

Leave a comment

Log in with to leave a comment.