Drawing Pixel Perfect Shapes On Surfaces With Sub Pixel Rendering

R

robproctor83

Guest
Hello,

Maybe this isn't possible with GM, but I'm hoping to get some insight into problem I'm having. In particular this is regarding the free asset in the marketplace called FG Lighting, but generally speaking this is an issue I run into with drawing shapes in a pixelated game.

My game uses an upscaled application surface, base resolution is 480x270 and it's upscaled by 4 to 1920x1080 which works great and gives me sub pixel rendering like I want. The problem is with drawing pixel perfect shapes with sub pixel rendering. For example, if I wanted to create a pixel circle I would have to draw it onto a surface that is 480x270 wide and then upcale that surface to the application surface which works, but if I wanted to move that circle by anything other than a whole number it flickers and moves erratically.

So, essentially what I am trying to figure out is how I can draw pixel shapes at the up-scaled resolution and keep sub pixel rendering. It seems I have to sacrifice one or the other (pixelated drawing or sub pixel rendering), but I get the feeling there is a way I am just missing it. By the way, just to clarify, I am specifically trying to retain the pixelated effect of drawing on a small surface, I understand it is possible to draw to an up-scaled surface and then scale it back down to get sub pixel rendering, but doing so will draw a smooth circle which is not what I want.

PS: I'm interested in knowing any solution possible, though I am only likely to implement it if it's not a performance issue. For example, my issue with FG lighting, I am able to resolve it by making the lights surface the size of the room instead of the view and then draw just the particular part of the surface that the view covers. That works exactly like I want, BUT it's not good on performance. There is a noticeable drop in overall performance when doing this which really sucks. I also went through the trouble of up-scaling drawing to the surface and then scaling it back down, which also worked but gave me unwanted sharp edges (which is the issue I am posting about now).
 
Last edited by a moderator:
C

Catastrophe

Guest
So upscaling the images themselves and just using a 1920x1080 base game isn't an option I take it? I'm wondering what is causing these performance issues and maybe there's a way to fix them without sacrificing your design. If FG lighting itself is actually causing performance issues, I'd use a different asset, there's more than one way to do lighting.
 
R

robproctor83

Guest
Hey Catastrophe, thanks for writing.

If I understand what your saying, even if I did make the base game 1920x1080 it wouldn't fix the problem ( I don't think) because ultimately if I draw the lighting at that resolution it will still have the unwanted smooth edges and if I draw it to a surface at 1/4th scale and then resize it up to the 1920x1080 it will then be missing the sub pixel rendering as movements drawn onto the surface at 1/4th scale will appear jagged when blown up... Hopefully I am explaining the issue clearly, it's confusing for sure.

FYI, I don't think it's an issue with FG lighting, from what I can tell the asset is actually very fast and runs much faster than a few of the others I have tried. The performance issue I am referring to is due to a hack I made to it. By default it draws to a surface the size of your view and then the surface essentially follows around the view. My problem is that my view moves in sub pixels so when the surface tries to follow it anytime it's movements are a fraction it causes the surface to stutter as it technically only moves in full pixels. My solution was to change how it works by making the surface the size of the room, instead of the size of the view, and rather than move the surface around with the view I instead just draw the part of the surface that the view is currently over. I had hoped that using surface_draw_part would be enough to prevent performance issue, but I guess the surface is just too big to be used efficiently.

My only other thought on this, which I don't know if it would work and even if it did it would be gross and I'm not sure I would be able to apply it to the lighting system... But, in the case of something like a moving circle I think it would be possible to draw that circle at base resolution onto a surface the size of the circle, then resize it to the full resolution, then redraw the circle surface onto another surface at full scale and then do the movements or whatever there. I can't see how I would do that with something like FG Lighting though, likely not even possible.
 
C

Catastrophe

Guest
Ah, yeah so it's how you're using FG lighting. Yeah I would not make it the whole room, looking at reviews, fg lighting can run terribly on bad computers meaning your game might be inacessible to some players. The stuttering issue should be resolved by just matching your view movement to your surface movement, like it sounds like you want to move the surface only when you've moved the view in end step, and your view should only move when it's moving a full pixel.

As for the lightning smoothness, I think I see what you mean, you want your general images to look blocky, but don't want the smoothness of the lighting. Yeah that's tricky. I wonder if you can intentionally screw with the surface by resizing it down and up again to force loss of resolution. In any case this might be out of my league.
 

HayManMarc

Member
My solution was to change how it works by making the surface the size of the room, instead of the size of the view, and rather than move the surface around with the view I instead just draw the part of the surface that the view is currently over. I had hoped that using surface_draw_part would be enough to prevent performance issue, but I guess the surface is just too big to be used efficiently.
Why not, instead of making the surface the size of the entire room, just do the math and make the surface the size of the view, then do your scaling?

And, about the circle, what would happen if you made the circle a Sprite, then used it the way you want? (create_sprite_from_surface)

I don't know if these suggestions will work, I'm just saying what I would try.
 
R

robproctor83

Guest
Catastrophe, why do you say FG lighting would run slower on older computers? And, do you have a suggestion for a good lighting system, I am open to better solutions.

HayManMarc, I have done just that with the view, but that is the issue, the view moves in sub pixels, but the lighting surface moves in single pixels. If I scale it up to get sub pixel rendering with it it also makes the edges of the shadows smooth rather than pixelated, which I also don't want. And yes, a sprite would not have this issue, but for dynamic shapes like the shadows casted by this lighting engine it's not possible to use a sprite. The circle was just a simple example to illustrate the problem I am facing.
 
C

Catastrophe

Guest
You should do your homework whenever you use an asset ;)

Capture.PNG

As for better lighting, I do not, I only know there's like a dozen ways.
I'm not saying you cant use FG, just that if your unoptimal method of using the whole room works, it may not work for everyone.
 
R

robproctor83

Guest
Oh you know what, that review was from me actually. This was after I had added that hack that I wrote about earlier, and then after realizing that was the issue the performance was optimal. I should probably respond back on there clarifying actually. I know I had looked around online to see if anyone had performance issues with it, so I thought maybe you had come across something I wasn't aware of.

Well, I am still curious if anyone knows what the best performing dynamic lighting system would be? From what I can tell FG lighting works the same way as the tutorial posted on the official blog in that it uses surfaces and shaders to draw the lighting.
https://www.yoyogames.com/blog/419/realtime-2d-lighting-in-gamemaker-studio-2-part-1
https://www.yoyogames.com/blog/420/realtime-2d-lighting-in-gamemaker-studio-2-part-2

I'd be interested in trying Nocturnes version,though I am not sure it would really be any faster or not.

https://marketplace.yoyogames.com/assets/5229/aura-2-0-lighting-engine

I had only tried implimenting two other systems. One that I built following a different tutorial which worked okay but was seemingly slow and difficult to setup. The other was one from the market, which the name escapes me now, but it was also not very fast. This was probably a year or two ago now so things may have changed since then.
 
Top