godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Allow high resolution art to be downscaled example: @2x = 0.5 scale. Useful for pixel art. #407

Open hamoom opened 4 years ago

hamoom commented 4 years ago

Describe the project you are working on: An Action RPG using pixel art

Describe the problem or limitation you are having in your project: I want to move and scale the camera using floating values without the sprites being distorted.

Describe how this feature / enhancement will help you overcome this problem or limitation: In other engines I solved this problem by importing my pixel art at 3x or 4x the normal size with the filter on.. then it allowed me to downscale the art to the original desired size. Since I was now using high resolution art without filtering my edges would be preserved despite using floating point values.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:

proposal

Describe implementation detail for your proposal (in code), if possible: You import a larger texture than you intend to use.. if its a 2x texture you'd set the control (look above) to 0.5 and the texture would then be able to scale properly without distortion. This is very useful for pixel art

If this enhancement will not be used often, can it be worked around with a few lines of script?: Not really. I've seen very complicated solutions involving adding a shader to each sprite that still aren't very effective. Other people recommending very complicated viewport math. This feature will be used often because people want to scale pixel art without distortion.

Is there a reason why this should be core and not an add-on in the asset library?: Pixel art games are extremely popular and scaling / rotation / panning sprites causes distortion as is. If you can import higher quality versions of them and scale down it solves all those problems. Look at the game I was attempting to port to godot as a reference to how well this works: https://www.youtube.com/watch?v=HIARx0kW7XM

golddotasksquestions commented 4 years ago

As I mentioned in my reply, if the effect you want to archive is something like this heartbeast tutorial, but not for individual objects but the whole viewport, then import settings won't help you. Godot uses "nearest neighbour" scaling throughout the 2D render engine. I think what we need is a "nearest neighbour" / "bicubic scaling" rendering option (checkbox) in the Project Settings.

Also, even though this video is already compressed by youtube, I do see jitter in your old project as well (0:23). To me it seems like this result is entirely achievable with Godots current setting options (like those I have outlined in my reply under Approach1)

hamoom commented 4 years ago

I think it has something to do with the conversion from my phone recording to youtube. But when you're playing my game the jitter is almost impossible to detect. I don't ever see any pixels becoming distorted etc. It's definitely a huge improvement from just using pixel art with filtering off.

In any case the implementation of this feature is beyond the scope of my knowledge. if you say we need a "bicubic scaling rendering option" I will take your word for it. I just know that in other engines / frameworks I do the following.

  1. set filtering to on for the whole project
  2. I add an oversized image
  3. I specify the intended size when I load the image

After that I can scale the game in all kinds of ways with very minimal distortion. It's an easy setup and it just works. You have to consider beginners trying to get their pixel art to look clean may find complicated viewport math and adding shaders a daunting thing to tackle.

golddotasksquestions commented 4 years ago

You have to consider beginners trying to get their pixel art to look clean may find complicated viewport math and adding shaders a daunting thing to tackle.

Yes, I absolutely agree. Which is why I wrote this comment.

I still think your are mixing up viewport stretch rendering setting with texture import options though.

hamoom commented 4 years ago

I probably am getting that mixed up. I appreciate your input. I'm a beginner with godot and I'm just trying to port my half finished project over. I know that I was able to get this working as intended in the other engine but I'm not sure exactly what specific settings are required to get it functioning in godot. Should I correct my screenshot to show a "bicubic scaling rendering option" as well?

I do know if you could add oversized assets to the game you'd need a place to specify how much you would like to scale them down by. Correct? The engine would need to know that your assets are 4x larger than you intend to display.

golddotasksquestions commented 4 years ago

I do know if you could add oversized assets to the game you'd need a place to specify how much you would like to scale them down by. Correct? The engine would need to know that your assets are 4x larger than you intend to display.

You can already do all that. Every Sprite has a Scale property. You can upscale your pixelart in your graphics software and then downscale it in Godot. It's just completely pointless. Not only will you have increased the filesize and memory print of your assets without any purpose, the engine will also still render your up-and-downscaled pixel graphic via "nearest neighbour", even if your filter option is enabled on import.

hamoom commented 4 years ago

I've tried doing that in godot. I added my art at 4x and scaled to 0.25 size. Yeah the result is identical. I see identical jitter. It did not solve my problem on it's own. Probably because of the nearest neighbor scaling you are mentioning.

The other issue with just scaling things down in godot is that the units get all messed up.
For example, a gigantic sprite that I scaled to 1/4 size appears to be moving 1/4 the speed. I have to now increase it's velocity by 4. The engine should allow you to scale your sprite down (in project settings or import I don't know) and consider it at a 1x scale. I think this is a lot more prevalent in mobile development. You have 2x, 3x, 4x assets etc but when you're writing code everything is considered to be it's 1x size.

You obviously know much more than I do. I don't understand the technical aspects of how these game engines work. I don't know what technique they use to downscale the art.

I just know that when I was using the original pixel art at 1x resolution and filtering off then I would have all the distortion you'd expect with floating point numbers. When I used filtering and high resolution art with downscaling then I could give the illusion that I was using low resolution art with minimal to no jitter.

golddotasksquestions commented 4 years ago

The other issue with just scaling things down in godot is that the units get all messed up. For example, a gigantic sprite that I scaled to 1/4 size appears to be moving 1/4 the speed. I have to now increase it's velocity by 4. The engine should allow you to scale your sprite down (in project settings or import I don't know) and consider it at a 1x scale. I think this is a lot more prevalent in mobile development. You have 2x, 3x, 4x assets etc but when you're writing code everything is considered to be it's 1x size.

The way you do this in Godot is by taking advantage of it's nodes. This for example would be the node structure of a simple player scene:

KinematicBody2D (this is the node you attach your script to control movement)
- CollisionShape2D
- Sprite (This node you just use to display your character as a graphic.)

This way you can scale the Sprite independently of the player movement logic.

hamoom commented 4 years ago

ah yeah thats exactly what my node tree looked like.. i think what i was thinking of is when i kept my oversized sprite at original scale and tried to just push the camera super far back to make it appear normal size. now my original velocity appeared slow. my bad on that one. I had tried so many things that I was getting confused.

anyway you can tell I'm an idiot and somehow solved this problem and published jitter free games.. so it shouldn't really be as hard as it is in godot.

makemefeelgr8 commented 11 months ago

It's crazy that this very simpliest feature have not been implemented in 3 years! How do you even develop a mobile game that looks equally good on a tablet and on a low-end device? Do you include 5 sets of sprites, one for each resolution?? Man, this is bad!

Calinou commented 11 months ago

It's crazy that this very simpliest feature have not been implemented in 3 years! How do you even develop a mobile game that looks equally good on a tablet and on a low-end device? Do you include 5 sets of sprites, one for each resolution?? Man, this is bad!

Follow the advice in the Multiple resolutions documentation: Reducing aliasing on downsampling

What this proposal suggests is less efficient in terms of video memory usage – it would increase the memory usage of all sprites by 4×, rather than just 1.33× like enabling mipmaps. Therefore, I don't think we should pursue that route.

For pixel art filtering at arbitrary scale factors (not just up to 2×), sharp bilinear is a better approach.

makemefeelgr8 commented 11 months ago

Follow the advice in the Multiple resolutions documentation: Reducing aliasing on downsampling

What this proposal suggests is less efficient in terms of video memory usage – it would increase the memory usage of all sprites by 4×, rather than just 1.33× like enabling mipmaps. Therefore, I don't think we should pursue that route.

For pixel art filtering at arbitrary scale factors (not just up to 2×), sharp bilinear is a better approach.

Yeah, I've seen that, and it is about as horrible, as it gets. All it says is "you can enable mipmaps on all your 2D textures". But it leaves way too many questions unanswered. Just to name a few: What is a mipmap? How do I enable it? Where is the manual about texture imports?

I'm curious: what do you expect a user will do at this point? They came looking for solutions, so you might as well provide them. Let's take a look at how your competitors do it: https://docs.unity3d.com/Manual/class-TextureImporter.html https://docs.unity3d.com/Manual/texture-mipmaps-introduction.html All relevant info is in the docs! There's even a definition of a mipmap, and some screenshots with import window. Just how cool is that!

So, if you don't care about implementing a quality of life feature, proposed here, you could at least add a link with the workaround to the docs. Like: "Yes, the engine doesn't really support proper texture scaling, and we're not going to implement it, but at least you can open the window X, enable the checkbox Y, and get somewhat similar results."

I wonder, what is the intended way to implement zooming. Enable mipmaps for all textures? Oh man...

Zireael07 commented 11 months ago

To put it in the simplest words possible, mipmaps are LODs for textures.

You enable mipmaps in the import dock for the texture. It's as easy as toggling a checkbox.

golddotasksquestions commented 11 months ago

@makemefeelgr8 I encourage you to not only check Unitys documentation, but Godots documentation as well: https://docs.godotengine.org/en/stable/tutorials/assets_pipeline/importing_images.html#mipmaps-generate

There is a lot of info about all of this in the "Multiple Resolutions" Godot docs page Calinou linked as well: https://docs.godotengine.org/en/stable/tutorials/rendering/multiple_resolutions.html#desktop-game

So to sum up, this is not about anyone not wanting to implement a "quality of life feature". All these features requested here are already implement in a much more useful manner than what is proposed here. You just have to learn how to use them.

makemefeelgr8 commented 11 months ago

You just have to learn how to use them.

This is exactly my point! The "mipmap" word in a document should be a link that leads here.