Weird issues with stencils

EDIT: After testing some more with solid fills instead of patterns, it looks like this is not only a case of my not appreciating how easy it is to get regular patterns to line up with each other exactly, but it’s the result of my “fixing” a “bug” from a couple years ago, when I already ran into this problem. So never mind this thread.

Synopsis: I’ve been simulating light sources by using a combination of a stencil image and a pattern drawn into an overlay sprite. Now that I’m trying to generate the stencil with drawing commands instead of pre-generated bitmaps, it’s not behaving at all like I expect. I’m wonder if this is a bug or if I’m using it incorrectly, and also whether there’s a better way to achieve the effect I want.

The problem I’m trying to fix: This GIF shows a circle of light around 2 of my characters, and around the headlights of the van. As the characters move, there’s a distracting amount of flickering around the edges of the light sources.
SasquatchersLightDithering
(Until now, I’ve just assumed that it was an inevitable side effect of using patterns on top of patterns. I’ve had it only updating at cell intervals, but that makes it look stuttery, like the frame rate is much worse than it actually is).

The technique I use: The game map is split into a couple of larger-than-screen-size sprites: the map background, which contains trees, rocks, and grid lines, and then the “light” overlay as a semi-transparent sprite which is on top of the map. To draw the light overlay, I first make a stencil image with a solid white background, then draw the light sources in black onto the stencil. Here’s what the stencil looks like (with my sprite characters floating on top):
Sasquatchers-Stencil
Then using the stencil, I do a fill rect with my “fog” pattern, assuming it would only draw in the white areas of the stencil and leave the rest transparent. Here’s that pattern:

    fogPattern       = { 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00 }

First Problem: In that stencil image, all of the light sources look the same to me. But in the game (top GIF), you can see that the top one looks like a solid white circle with no dithered edge, while the lower sources have a gradient edge. Currently the top one is a test that I’m drawing programmatically with patterns and drawCircleAtPoint, but the ones around the characters and the van are pre-generated in photoshop that I’m just doing with drawImage. I don’t understand why they have different effects when used as a stencil.

Second Problem: When the light source moves (top GIF), the circle seems to swap between dithered-edge and solid circle every frame, more than just pattern-on-pattern drawing would suggest to me.

Does this seem like a bug? Am I expecting too much from the stencil & pattern drawing systems? Is there a better/more efficient way to get this kind of effect? Thanks in advance for any help.

What happens if you move the light source on top (the one that looks white) by exactly one pixel? Direction doesn’t matter.

If the issue is with your patterns it should show correctly after moving.

After a quick check in Photoshop it seems you patterns create this effect when the fog pattern align perfectly with the dithering in your lights.

I am not sure what would be the best way to tackle the issue but here some ideas:

  • Align your light on the fog grid. Something like light.x = light.x - (light.x%2) but that might create less fluid movement for the light.
  • Use a different dithering pattern for the light instead of bayer to avoid repetitive pattern. Maybe one with erro correction, or blue noise will have less structure and you would avoid that all pixels of the fog align with the light dither pattern.

@veubeke and @Nic : thanks for the suggestions, that was my first thought as well. I have a little helper function that lets me move my test circle freely around the screen, but it always shows up as a solid-outline circle, suggesting to me that it’s not simply the pattern of my stencil perfectly lining up with my fog pattern.
I think the idea of a noisier pattern might work, but a huge part of the appeal of working on a 1-bit screen again was seeing all the old familiar Mac Classic regular dithering patterns again. They’re oddly nostalgic even if they’re not realistic.

EDIT: Wait, scratch that, I think I need to experiment some more. I keep forgetting that both my stencil AND my fog have a one-pixel off pattern, so getting them to go in and out of alignment is more likely than I think. I’ll revisit what I’m doing.

3 Likes